[9411] More SpellEffectIndex using in apropriate cases
[getmangos.git] / src / game / SpellEffects.cpp
blob9a88a6be391b66115c6449d281600c244a46c6e9
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::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::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectSummonAllTotems, // 97 SPELL_EFFECT_SUMMON_ALL_TOTEMS
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
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::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(SpellEffectIndex /*eff_idx*/)
227 sLog.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(SpellEffectIndex /*eff_idx*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(SpellEffectIndex eff_idx)
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[eff_idx];
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(SpellEffectIndex /*eff_idx*/)
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::EffectEnvironmentalDMG(SpellEffectIndex eff_idx)
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(eff_idx);
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(SpellEffectIndex 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
325 case 70492: case 72505: // Ooze Eruption
326 case 71904: // Chaos Bane
327 case 72624: case 72625: // Ooze Eruption
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
345 // Intercept (warrior spell trigger)
346 case 20253:
347 case 61491:
349 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
350 break;
352 // Cataclysmic Bolt
353 case 38441:
355 damage = unitTarget->GetMaxHealth() / 2;
356 break;
358 // Tympanic Tantrum
359 case 62775:
361 damage = unitTarget->GetMaxHealth() / 10;
362 break;
364 // Hand of Rekoning (name not have typos ;) )
365 case 67485:
366 damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
367 break;
369 break;
371 case SPELLFAMILY_MAGE:
372 // remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
373 // NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
374 if ((m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_ARCANE) && !(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000)))
375 m_caster->RemoveAurasDueToSpell(36032); // Arcane Blast buff
376 break;
377 case SPELLFAMILY_WARRIOR:
379 // Bloodthirst
380 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
382 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
384 // Shield Slam
385 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
386 damage += int32(m_caster->GetShieldBlockValue());
387 // Victory Rush
388 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
390 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
391 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
393 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
394 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
395 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
396 // Heroic Throw ${$m1+$AP*.50}
397 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
398 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
399 // Shockwave ${$m3/100*$AP}
400 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
402 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
403 if (pct > 0)
404 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
405 break;
407 // Thunder Clap
408 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
410 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
412 break;
414 case SPELLFAMILY_WARLOCK:
416 // Incinerate Rank 1 & 2
417 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
419 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
420 // Check aura state for speed but aura state set not only for Immolate spell
421 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
423 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
424 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
426 // Immolate
427 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
428 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
430 damage += damage/4;
431 break;
436 // Shadowflame
437 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
439 // Apply DOT part
440 switch(m_spellInfo->Id)
442 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
443 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
444 default:
445 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
446 break;
449 // Conflagrate - consumes Immolate or Shadowflame
450 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
452 Aura const* aura = NULL; // found req. aura for damage calculation
454 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
455 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
457 // for caster applied auras only
458 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
459 (*i)->GetCasterGUID()!=m_caster->GetGUID())
460 continue;
462 // Immolate
463 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
465 aura = *i; // it selected always if exist
466 break;
469 // Shadowflame
470 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
471 aura = *i; // remember but wait possible Immolate as primary priority
474 // found Immolate or Shadowflame
475 if (aura)
477 // DoT not have applied spell bonuses in m_amount
478 int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
479 damage += damagetick * 4;
481 // Glyph of Conflagrate
482 if (!m_caster->HasAura(56235))
483 unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
484 break;
487 break;
489 case SPELLFAMILY_PRIEST:
491 // Shadow Word: Death - deals damage equal to damage done to caster
492 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
493 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
494 // Improved Mind Blast (Mind Blast in shadow form bonus)
495 else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000)))
497 Unit::AuraList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
498 for(Unit::AuraList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
500 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
501 ((*i)->GetSpellProto()->SpellIconID == 95))
503 int chance = (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1);
504 if (roll_chance_i(chance))
505 // Mind Trauma
506 m_caster->CastSpell(unitTarget, 48301, true);
507 break;
511 break;
513 case SPELLFAMILY_DRUID:
515 // Ferocious Bite
516 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
518 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
519 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
520 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
521 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
522 uint32 energy = m_caster->GetPower(POWER_ENERGY);
523 uint32 used_energy = energy > 30 ? 30 : energy;
524 damage += int32(used_energy * multiple);
525 m_caster->SetPower(POWER_ENERGY,energy-used_energy);
527 // Rake
528 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_ADD_COMBO_POINTS)
530 // $AP*0.01 bonus
531 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
533 // Swipe
534 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
536 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
538 break;
540 case SPELLFAMILY_ROGUE:
542 // Envenom
543 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
545 // consume from stack dozes not more that have combo-points
546 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
548 Aura *poison = 0;
549 // Lookup for Deadly poison (only attacker applied)
550 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
551 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
552 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
553 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
554 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
556 poison = *itr;
557 break;
559 // count consumed deadly poison doses at target
560 if (poison)
562 bool needConsume = true;
563 uint32 spellId = poison->GetId();
564 uint32 doses = poison->GetStackAmount();
565 if (doses > combo)
566 doses = combo;
568 // Master Poisoner
569 Unit::AuraList const& auraList = ((Player*)m_caster)->GetAurasByType(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL);
570 for(Unit::AuraList::const_iterator iter = auraList.begin(); iter!=auraList.end(); ++iter)
572 if ((*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellProto()->SpellIconID == 1960)
574 if (int32 chance = (*iter)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2))
575 if (roll_chance_i(chance))
576 needConsume = false;
578 break;
582 if(needConsume)
583 for (uint32 i = 0; i < doses; ++i)
584 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
586 damage *= doses;
587 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
589 // Eviscerate and Envenom Bonus Damage (item set effect)
590 if(m_caster->GetDummyAura(37169))
591 damage += ((Player*)m_caster)->GetComboPoints()*40;
594 // Eviscerate
595 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
597 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
599 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
600 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
602 // Eviscerate and Envenom Bonus Damage (item set effect)
603 if(m_caster->GetDummyAura(37169))
604 damage += combo*40;
607 // Gouge
608 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
610 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
612 // Instant Poison
613 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
615 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
617 // Wound Poison
618 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
620 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
622 break;
624 case SPELLFAMILY_HUNTER:
626 //Gore
627 if (m_spellInfo->SpellIconID == 1578)
629 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
630 damage *= 2;
632 // Mongoose Bite
633 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
635 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
637 // Counterattack
638 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
640 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
642 // Arcane Shot
643 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
645 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
647 // Steady Shot
648 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
650 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
651 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
653 // Explosive Trap Effect
654 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
656 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
658 break;
660 case SPELLFAMILY_PALADIN:
662 // Judgement of Righteousness - receive benefit from Spell Damage and Attack power
663 if (m_spellInfo->Id == 20187)
665 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
666 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
667 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
668 damage += int32(ap * 0.2f) + int32(holy * 32 / 100);
670 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
671 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
673 uint32 debuf_id;
674 switch(m_spellInfo->Id)
676 case 53733: debuf_id = 53742; break;// Judgement of Corruption -> Blood Corruption
677 case 31804: debuf_id = 31803; break;// Judgement of Vengeance -> Holy Vengeance
678 default: return;
681 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
682 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
683 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
684 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
685 // Get stack of Holy Vengeance on the target added by caster
686 uint32 stacks = 0;
687 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
688 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
690 if( ((*itr)->GetId() == debuf_id) && (*itr)->GetCasterGUID()==m_caster->GetGUID())
692 stacks = (*itr)->GetStackAmount();
693 break;
696 // + 10% for each application of Holy Vengeance on the target
697 if(stacks)
698 damage += damage * stacks * 10 /100;
700 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
701 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
703 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
704 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
705 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
706 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
708 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
709 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
711 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
712 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
713 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
714 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
716 // Hammer of the Righteous
717 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
719 // Add main hand dps * effect[2] amount
720 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
721 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
722 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
724 // Shield of Righteousness
725 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
727 damage+=int32(m_caster->GetShieldBlockValue());
729 // Judgement
730 else if (m_spellInfo->Id == 54158)
732 // [1 + 0.25 * SPH + 0.16 * AP]
733 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
735 break;
739 if(damage >= 0)
740 m_damage += damage;
744 void Spell::EffectDummy(SpellEffectIndex eff_idx)
746 if (!unitTarget && !gameObjTarget && !itemTarget)
747 return;
749 // selection by spell family
750 switch(m_spellInfo->SpellFamilyName)
752 case SPELLFAMILY_GENERIC:
754 switch(m_spellInfo->Id )
756 case 8063: // Deviate Fish
758 if (m_caster->GetTypeId() != TYPEID_PLAYER)
759 return;
761 uint32 spell_id = 0;
762 switch(urand(1,5))
764 case 1: spell_id = 8064; break; // Sleepy
765 case 2: spell_id = 8065; break; // Invigorate
766 case 3: spell_id = 8066; break; // Shrink
767 case 4: spell_id = 8067; break; // Party Time!
768 case 5: spell_id = 8068; break; // Healthy Spirit
770 m_caster->CastSpell(m_caster, spell_id, true, NULL);
771 return;
773 case 8213: // Savory Deviate Delight
775 if (m_caster->GetTypeId() != TYPEID_PLAYER)
776 return;
778 uint32 spell_id = 0;
779 switch(urand(1,2))
781 // Flip Out - ninja
782 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
783 // Yaaarrrr - pirate
784 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
786 m_caster->CastSpell(m_caster,spell_id,true,NULL);
787 return;
789 case 8593: // Symbol of life (restore creature to life)
790 case 31225: // Shimmering Vessel (restore creature to life)
792 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
793 return;
794 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
795 return;
797 case 13120: // net-o-matic
799 if (!unitTarget)
800 return;
802 uint32 spell_id = 0;
804 uint32 roll = urand(0, 99);
806 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
807 spell_id = 16566;
808 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
809 spell_id = 13119;
810 else // normal root
811 spell_id = 13099;
813 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
814 return;
816 case 13567: // Dummy Trigger
818 // can be used for different aura triggering, so select by aura
819 if (!m_triggeredByAuraSpell || !unitTarget)
820 return;
822 switch(m_triggeredByAuraSpell->Id)
824 case 26467: // Persistent Shield
825 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
826 break;
827 default:
828 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
829 break;
831 return;
833 case 15998: // Capture Worg Pup
834 case 29435: // Capture Female Kaliri Hatchling
836 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
837 return;
839 Creature* creatureTarget = (Creature*)unitTarget;
841 creatureTarget->ForcedDespawn();
842 return;
844 case 16589: // Noggenfogger Elixir
846 if (m_caster->GetTypeId() != TYPEID_PLAYER)
847 return;
849 uint32 spell_id = 0;
850 switch(urand(1, 3))
852 case 1: spell_id = 16595; break;
853 case 2: spell_id = 16593; break;
854 default:spell_id = 16591; break;
857 m_caster->CastSpell(m_caster, spell_id, true, NULL);
858 return;
860 case 17251: // Spirit Healer Res
862 if (!unitTarget)
863 return;
865 Unit* caster = GetAffectiveCaster();
867 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
869 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
870 data << uint64(unitTarget->GetGUID());
871 ((Player*)caster)->GetSession()->SendPacket( &data );
873 return;
875 case 17271: // Test Fetid Skull
877 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
878 return;
880 uint32 spell_id = roll_chance_i(50)
881 ? 17269 // Create Resonating Skull
882 : 17270; // Create Bone Dust
884 m_caster->CastSpell(m_caster, spell_id, true, NULL);
885 return;
887 case 20577: // Cannibalize
888 if (unitTarget)
889 m_caster->CastSpell(m_caster, 20578, false, NULL);
890 return;
891 case 23019: // Crystal Prison Dummy DND
893 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
894 return;
896 Creature* creatureTarget = (Creature*)unitTarget;
897 if (creatureTarget->isPet())
898 return;
900 GameObject* pGameObj = new GameObject;
902 Map *map = creatureTarget->GetMap();
904 // create before death for get proper coordinates
905 if (!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
906 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
907 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
909 delete pGameObj;
910 return;
913 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
914 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
915 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
916 pGameObj->SetSpellId(m_spellInfo->Id);
918 creatureTarget->ForcedDespawn();
920 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
921 map->Add(pGameObj);
923 return;
925 case 23074: // Arcanite Dragonling
926 if (!m_CastItem)
927 return;
928 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
929 return;
930 case 23075: // Mithril Mechanical Dragonling
931 if (!m_CastItem)
932 return;
933 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
934 return;
935 case 23076: // Mechanical Dragonling
936 if (!m_CastItem)
937 return;
938 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
939 return;
940 case 23133: // Gnomish Battle Chicken
941 if (!m_CastItem)
942 return;
943 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
944 return;
945 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
947 int32 r = irand(0, 119);
948 if (r < 20) // Transporter Malfunction - 1/6 polymorph
949 m_caster->CastSpell(m_caster, 23444, true);
950 else if (r < 100) // Evil Twin - 4/6 evil twin
951 m_caster->CastSpell(m_caster, 23445, true);
952 else // Transporter Malfunction - 1/6 miss the target
953 m_caster->CastSpell(m_caster, 36902, true);
954 return;
956 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
957 if (roll_chance_i(50)) // Gadgetzan Transporter - success
958 m_caster->CastSpell(m_caster, 23441, true);
959 else // Gadgetzan Transporter Failure - failure
960 m_caster->CastSpell(m_caster, 23446, true);
961 return;
962 case 23645: // Hourglass Sand
963 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
964 return;
965 case 23725: // Gift of Life (warrior bwl trinket)
966 m_caster->CastSpell(m_caster, 23782, true);
967 m_caster->CastSpell(m_caster, 23783, true);
968 return;
969 case 25860: // Reindeer Transformation
971 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
972 return;
974 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
975 float speed = m_caster->GetSpeedRate(MOVE_RUN);
977 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
979 //5 different spells used depending on mounted speed and if mount can fly or not
980 if (flyspeed >= 4.1f)
981 // Flying Reindeer
982 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
983 else if (flyspeed >= 3.8f)
984 // Flying Reindeer
985 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
986 else if (flyspeed >= 1.6f)
987 // Flying Reindeer
988 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
989 else if (speed >= 2.0f)
990 // Reindeer
991 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
992 else
993 // Reindeer
994 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
996 return;
998 case 26074: // Holiday Cheer
999 // implemented at client side
1000 return;
1001 case 28006: // Arcane Cloaking
1003 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
1004 // Naxxramas Entry Flag Effect DND
1005 m_caster->CastSpell(unitTarget, 29294, true);
1006 return;
1008 case 29200: // Purify Helboar Meat
1010 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1011 return;
1013 uint32 spell_id = roll_chance_i(50)
1014 ? 29277 // Summon Purified Helboar Meat
1015 : 29278; // Summon Toxic Helboar Meat
1017 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1018 return;
1020 case 29858: // Soulshatter
1021 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
1022 m_caster->CastSpell(unitTarget,32835,true);
1023 return;
1024 case 30458: // Nigh Invulnerability
1025 if (!m_CastItem)
1026 return;
1027 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1028 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1029 else // Complete Vulnerability - backfire in 14% casts
1030 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1031 return;
1032 case 30507: // Poultryizer
1033 if(!m_CastItem)
1034 return;
1035 if (roll_chance_i(80)) // Poultryized! - success
1036 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1037 else // Poultryized! - backfire 20%
1038 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1039 return;
1040 case 33060: // Make a Wish
1042 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1043 return;
1045 uint32 spell_id = 0;
1047 switch(urand(1,5))
1049 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1050 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1051 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1052 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1053 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1056 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1057 return;
1059 case 34665: //Administer Antidote
1061 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1062 return;
1063 // Spell has scriptable target but for sure.
1064 if (unitTarget->GetTypeId() != TYPEID_UNIT)
1065 return;
1067 uint32 health = unitTarget->GetHealth();
1068 float x, y, z, o;
1070 unitTarget->GetPosition(x, y, z);
1071 o = unitTarget->GetOrientation();
1072 ((Creature*)unitTarget)->ForcedDespawn();
1074 if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000))
1076 summon->SetHealth(health);
1077 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon);
1079 if (summon->AI())
1080 summon->AI()->AttackStart(m_caster);
1082 return;
1084 case 35745: // Socrethar's Stone
1086 uint32 spell_id;
1087 switch(m_caster->GetAreaId())
1089 case 3900: spell_id = 35743; break; // Socrethar Portal
1090 case 3742: spell_id = 35744; break; // Socrethar Portal
1091 default: return;
1094 m_caster->CastSpell(m_caster, spell_id, true);
1095 return;
1097 case 37674: // Chaos Blast
1099 if (!unitTarget)
1100 return;
1102 int32 basepoints0 = 100;
1103 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1104 return;
1106 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1108 // selecting one from Bloodstained Fortune item
1109 uint32 newitemid;
1110 switch(urand(1, 20))
1112 case 1: newitemid = 32688; break;
1113 case 2: newitemid = 32689; break;
1114 case 3: newitemid = 32690; break;
1115 case 4: newitemid = 32691; break;
1116 case 5: newitemid = 32692; break;
1117 case 6: newitemid = 32693; break;
1118 case 7: newitemid = 32700; break;
1119 case 8: newitemid = 32701; break;
1120 case 9: newitemid = 32702; break;
1121 case 10: newitemid = 32703; break;
1122 case 11: newitemid = 32704; break;
1123 case 12: newitemid = 32705; break;
1124 case 13: newitemid = 32706; break;
1125 case 14: newitemid = 32707; break;
1126 case 15: newitemid = 32708; break;
1127 case 16: newitemid = 32709; break;
1128 case 17: newitemid = 32710; break;
1129 case 18: newitemid = 32711; break;
1130 case 19: newitemid = 32712; break;
1131 case 20: newitemid = 32713; break;
1132 default:
1133 return;
1136 DoCreateItem(eff_idx, newitemid);
1137 return;
1139 // Demon Broiled Surprise
1140 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1141 case 43723:
1143 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1144 return;
1146 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1147 return;
1150 case 44875: // Complete Raptor Capture
1152 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1153 return;
1155 Creature* creatureTarget = (Creature*)unitTarget;
1157 creatureTarget->ForcedDespawn();
1159 //cast spell Raptor Capture Credit
1160 m_caster->CastSpell(m_caster, 42337, true, NULL);
1161 return;
1163 case 44997: // Converting Sentry
1165 //Converted Sentry Credit
1166 m_caster->CastSpell(m_caster, 45009, true);
1167 return;
1169 case 45030: // Impale Emissary
1171 // Emissary of Hate Credit
1172 m_caster->CastSpell(m_caster, 45088, true);
1173 return;
1175 case 49357: // Brewfest Mount Transformation
1176 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1177 return;
1179 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1180 return;
1182 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1184 // Ram for Alliance, Kodo for Horde
1185 if (((Player *)m_caster)->GetTeam() == ALLIANCE)
1187 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1188 // 100% Ram
1189 m_caster->CastSpell(m_caster, 43900, true);
1190 else
1191 // 60% Ram
1192 m_caster->CastSpell(m_caster, 43899, true);
1194 else
1196 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1197 // 100% Kodo
1198 m_caster->CastSpell(m_caster, 49379, true);
1199 else
1200 // 60% Kodo
1201 m_caster->CastSpell(m_caster, 49378, true);
1203 return;
1204 case 50243: // Teach Language
1206 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1207 return;
1209 // spell has a 1/3 chance to trigger one of the below
1210 if (roll_chance_i(66))
1211 return;
1212 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1214 // 1000001 - gnomish binary
1215 m_caster->CastSpell(m_caster, 50242, true);
1217 else
1219 // 01001000 - goblin binary
1220 m_caster->CastSpell(m_caster, 50246, true);
1223 return;
1225 case 46167: // Planning for the Future: Create Snowfall Glade Pup Cover
1226 case 50926: // Gluttonous Lurkers: Create Zul'Drak Rat Cover
1227 case 51026: // Create Drakkari Medallion Cover
1228 case 51592: // Pickup Primordial Hatchling
1229 case 51961: // Captured Chicken Cover
1231 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
1232 return;
1234 uint32 spellId = 0;
1236 switch(m_spellInfo->Id)
1238 case 46167: spellId = 46773; break;
1239 case 50926: spellId = 50927; break;
1240 case 51026: spellId = 50737; break;
1241 case 51592: spellId = 51593; break;
1242 case 51961: spellId = 51037; break;
1245 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(spellId))
1247 unitTarget->CastSpell(m_caster, spellId, true);
1249 Creature* creatureTarget = (Creature*)unitTarget;
1251 if (const SpellCastTimesEntry *pCastTime = sSpellCastTimesStore.LookupEntry(pSpell->CastingTimeIndex))
1252 creatureTarget->ForcedDespawn(pCastTime->CastTime + 1);
1254 return;
1256 case 46797: // Quest - Borean Tundra - Set Explosives Cart
1257 if (!unitTarget)
1258 return;
1259 // Quest - Borean Tundra - Summon Explosives Cart
1260 unitTarget->CastSpell(unitTarget,46798,true,m_CastItem,NULL,m_originalCasterGUID);
1261 break;
1262 case 51582: // Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1264 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1265 return;
1267 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1268 bg->EventPlayerDroppedFlag((Player*)m_caster);
1270 m_caster->CastSpell(m_caster, 30452, true, NULL);
1271 return;
1273 case 52308: // Take Sputum Sample
1275 switch(eff_idx)
1277 case EFFECT_INDEX_0:
1279 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
1280 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
1282 if (m_caster->HasAura(reqAuraID, EFFECT_INDEX_0))
1283 m_caster->CastSpell(m_caster, spellID, true, NULL);
1284 return;
1286 case EFFECT_INDEX_1:
1287 return; // additional data for dummy[0]
1289 return;
1291 case 52759: // Ancestral Awakening
1292 if (!unitTarget)
1293 return;
1294 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1295 return;
1296 case 52845: // Brewfest Mount Transformation (Faction Swap)
1297 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1298 return;
1300 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1301 return;
1303 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1305 // Ram for Horde, Kodo for Alliance
1306 if (((Player *)m_caster)->GetTeam() == HORDE)
1308 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1309 // Swift Brewfest Ram, 100% Ram
1310 m_caster->CastSpell(m_caster, 43900, true);
1311 else
1312 // Brewfest Ram, 60% Ram
1313 m_caster->CastSpell(m_caster, 43899, true);
1315 else
1317 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1318 // Great Brewfest Kodo, 100% Kodo
1319 m_caster->CastSpell(m_caster, 49379, true);
1320 else
1321 // Brewfest Riding Kodo, 60% Kodo
1322 m_caster->CastSpell(m_caster, 49378, true);
1324 return;
1325 case 53341: // Rune of Cinderglacier
1326 case 53343: // Rune of Razorice
1328 // Runeforging Credit
1329 m_caster->CastSpell(m_caster, 54586, true);
1330 return;
1332 case 55004: // Nitro Boosts
1333 if (!m_CastItem)
1334 return;
1335 if (roll_chance_i(95)) // Nitro Boosts - success
1336 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1337 else // Knocked Up - backfire 5%
1338 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1339 return;
1340 case 58418: // Portal to Orgrimmar
1341 case 58420: // Portal to Stormwind
1342 return; // implemented in EffectScript[0]
1343 case 59640: // Underbelly Elixir
1345 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1346 return;
1348 uint32 spell_id = 0;
1349 switch(urand(1,3))
1351 case 1: spell_id = 59645; break;
1352 case 2: spell_id = 59831; break;
1353 case 3: spell_id = 59843; break;
1355 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1356 return;
1358 case 60932: // Disengage (one from creature versions)
1359 if (!unitTarget)
1360 return;
1361 m_caster->CastSpell(unitTarget,60934,true,NULL);
1362 return;
1363 case 67019: // Flask of the North
1365 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1366 return;
1368 uint32 spell_id = 0;
1369 switch(m_caster->getClass())
1371 case CLASS_WARRIOR:
1372 case CLASS_DEATH_KNIGHT:
1373 spell_id = 67018; // STR for Warriors, Death Knights
1374 break;
1375 case CLASS_ROGUE:
1376 case CLASS_HUNTER:
1377 spell_id = 67017; // AP for Rogues, Hunters
1378 break;
1379 case CLASS_PRIEST:
1380 case CLASS_MAGE:
1381 case CLASS_WARLOCK:
1382 spell_id = 67016; // SPD for Priests, Mages, Warlocks
1383 break;
1384 case CLASS_SHAMAN:
1385 // random (SPD, AP)
1386 spell_id = roll_chance_i(50) ? 67016 : 67017;
1387 break;
1388 case CLASS_PALADIN:
1389 case CLASS_DRUID:
1390 default:
1391 // random (SPD, STR)
1392 spell_id = roll_chance_i(50) ? 67016 : 67018;
1393 break;
1395 m_caster->CastSpell(m_caster, spell_id, true);
1396 return;
1399 break;
1401 case SPELLFAMILY_MAGE:
1402 switch(m_spellInfo->Id )
1404 case 11958: // Cold Snap
1406 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1407 return;
1409 // immediately finishes the cooldown on Frost spells
1410 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1411 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1413 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1415 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1416 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1417 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1419 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1421 else
1422 ++itr;
1424 return;
1426 case 31687: // Summon Water Elemental
1428 if (m_caster->HasAura(70937)) // Glyph of Eternal Water (permanent limited by known spells version)
1429 m_caster->CastSpell(m_caster, 70908, true);
1430 else // temporary version
1431 m_caster->CastSpell(m_caster, 70907, true);
1432 return;
1434 case 32826: // Polymorph Cast Visual
1436 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1438 //Polymorph Cast Visual Rank 1
1439 const uint32 spell_list[6] = {
1440 32813, // Squirrel Form
1441 32816, // Giraffe Form
1442 32817, // Serpent Form
1443 32818, // Dragonhawk Form
1444 32819, // Worgen Form
1445 32820 // Sheep Form
1447 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1449 return;
1452 break;
1453 case SPELLFAMILY_WARRIOR:
1454 // Charge
1455 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1457 int32 chargeBasePoints0 = damage;
1458 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1459 return;
1461 // Execute
1462 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1464 if(!unitTarget)
1465 return;
1467 uint32 rage = m_caster->GetPower(POWER_RAGE);
1469 // up to max 30 rage cost
1470 if(rage > 300)
1471 rage = 300;
1473 // Glyph of Execution bonus
1474 uint32 rage_modified = rage;
1476 if (Aura *aura = m_caster->GetDummyAura(58367))
1477 rage_modified += aura->GetModifier()->m_amount*10;
1479 int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[eff_idx] +
1480 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1482 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1484 // Sudden Death
1485 if(m_caster->HasAura(52437))
1487 Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
1488 for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1490 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1491 if ((*itr)->GetSpellProto()->SpellIconID == 1989)
1493 // saved rage top stored in next affect
1494 uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1)*10;
1495 if(lastrage < rage)
1496 rage -= lastrage;
1497 break;
1502 m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
1503 return;
1505 // Slam
1506 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1508 if(!unitTarget)
1509 return;
1511 // dummy cast itself ignored by client in logs
1512 m_caster->CastCustomSpell(unitTarget,50782,&damage,NULL,NULL,true);
1513 return;
1515 // Concussion Blow
1516 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1518 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1519 return;
1522 switch(m_spellInfo->Id)
1524 // Warrior's Wrath
1525 case 21977:
1527 if (!unitTarget)
1528 return;
1529 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1530 return;
1532 // Last Stand
1533 case 12975:
1535 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1536 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1537 return;
1539 // Bloodthirst
1540 case 23881:
1542 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1543 return;
1546 break;
1547 case SPELLFAMILY_WARLOCK:
1548 // Life Tap
1549 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1551 // In 303 exist spirit depend
1552 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1553 switch (m_spellInfo->Id)
1555 case 1454: damage+=spirit; break;
1556 case 1455: damage+=spirit*15/10; break;
1557 case 1456: damage+=spirit*2; break;
1558 case 11687: damage+=spirit*25/10; break;
1559 case 11688:
1560 case 11689:
1561 case 27222:
1562 case 57946: damage+=spirit*3; break;
1563 default:
1564 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1565 return;
1567 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1568 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1569 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1571 // Shouldn't Appear in Combat Log
1572 unitTarget->ModifyHealth(-damage);
1574 int32 mana = damage;
1575 // Improved Life Tap mod
1576 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1577 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1579 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1580 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1582 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1584 // Mana Feed
1585 int32 manaFeedVal = 0;
1586 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1587 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1589 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1590 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1592 if (manaFeedVal > 0)
1594 manaFeedVal = manaFeedVal * mana / 100;
1595 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1598 else
1599 SendCastResult(SPELL_FAILED_FIZZLE);
1600 return;
1602 break;
1603 case SPELLFAMILY_PRIEST:
1604 // Penance
1605 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1607 if (!unitTarget)
1608 return;
1610 int hurt = 0;
1611 int heal = 0;
1612 switch(m_spellInfo->Id)
1614 case 47540: hurt = 47758; heal = 47757; break;
1615 case 53005: hurt = 53001; heal = 52986; break;
1616 case 53006: hurt = 53002; heal = 52987; break;
1617 case 53007: hurt = 53003; heal = 52988; break;
1618 default:
1619 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1620 return;
1622 if (m_caster->IsFriendlyTo(unitTarget))
1623 m_caster->CastSpell(unitTarget, heal, true);
1624 else
1625 m_caster->CastSpell(unitTarget, hurt, true);
1626 return;
1628 break;
1629 case SPELLFAMILY_DRUID:
1630 // Starfall
1631 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100)
1633 //Shapeshifting into an animal form or mounting cancels the effect.
1634 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1636 if(m_triggeredByAuraSpell)
1637 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1638 return;
1641 //Any effect which causes you to lose control of your character will supress the starfall effect.
1642 if (m_caster->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
1643 return;
1645 switch(m_spellInfo->Id)
1647 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1648 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1649 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1650 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1651 default:
1652 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1653 return;
1656 break;
1657 case SPELLFAMILY_ROGUE:
1658 switch(m_spellInfo->Id )
1660 case 5938: // Shiv
1662 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1663 return;
1665 Player *pCaster = ((Player*)m_caster);
1667 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1668 if (!item)
1669 return;
1671 // all poison enchantments is temporary
1672 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1673 if (!enchant_id)
1674 return;
1676 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1677 if (!pEnchant)
1678 return;
1680 for (int s=0;s<3;s++)
1682 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1683 continue;
1685 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1686 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1687 continue;
1689 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1692 m_caster->CastSpell(unitTarget, 5940, true);
1693 return;
1695 case 14185: // Preparation
1697 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1698 return;
1700 //immediately finishes the cooldown on certain Rogue abilities
1701 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1702 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1704 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1706 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1707 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1708 else
1709 ++itr;
1711 return;
1713 case 31231: // Cheat Death
1715 m_caster->CastSpell(m_caster, 45182, true);
1716 return;
1719 break;
1720 case SPELLFAMILY_HUNTER:
1721 // Steady Shot
1722 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1724 if (!unitTarget || !unitTarget->isAlive())
1725 return;
1727 bool found = false;
1729 // check dazed affect
1730 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1731 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1733 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1735 found = true;
1736 break;
1740 if (found)
1741 m_damage+= damage;
1742 return;
1745 // Disengage
1746 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
1748 Unit* target = unitTarget;
1749 uint32 spellid;
1750 switch(m_spellInfo->Id)
1752 case 57635: spellid = 57636; break; // one from creature cases
1753 case 61507: spellid = 61508; break; // one from creature cases
1754 default:
1755 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
1756 return;
1758 if (!target || !target->isAlive())
1759 return;
1760 m_caster->CastSpell(target,spellid,true,NULL);
1763 switch(m_spellInfo->Id)
1765 case 23989: // Readiness talent
1767 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1768 return;
1770 //immediately finishes the cooldown for hunter abilities
1771 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
1772 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1774 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1776 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1777 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1778 else
1779 ++itr;
1781 return;
1783 case 37506: // Scatter Shot
1785 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1786 return;
1788 // break Auto Shot and autohit
1789 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1790 m_caster->AttackStop();
1791 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1792 return;
1794 // Last Stand
1795 case 53478:
1797 if (!unitTarget)
1798 return;
1799 int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
1800 unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1801 return;
1803 // Master's Call
1804 case 53271:
1806 Pet* pet = m_caster->GetPet();
1807 if (!pet || !unitTarget)
1808 return;
1810 pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true);
1811 return;
1814 break;
1815 case SPELLFAMILY_PALADIN:
1816 switch(m_spellInfo->SpellIconID)
1818 case 156: // Holy Shock
1820 if (!unitTarget)
1821 return;
1823 int hurt = 0;
1824 int heal = 0;
1826 switch(m_spellInfo->Id)
1828 case 20473: hurt = 25912; heal = 25914; break;
1829 case 20929: hurt = 25911; heal = 25913; break;
1830 case 20930: hurt = 25902; heal = 25903; break;
1831 case 27174: hurt = 27176; heal = 27175; break;
1832 case 33072: hurt = 33073; heal = 33074; break;
1833 case 48824: hurt = 48822; heal = 48820; break;
1834 case 48825: hurt = 48823; heal = 48821; break;
1835 default:
1836 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1837 return;
1840 if (m_caster->IsFriendlyTo(unitTarget))
1841 m_caster->CastSpell(unitTarget, heal, true);
1842 else
1843 m_caster->CastSpell(unitTarget, hurt, true);
1845 return;
1847 case 561: // Judgement of command
1849 if (!unitTarget)
1850 return;
1852 uint32 spell_id = m_currentBasePoints[eff_idx]+1;
1853 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1854 if (!spell_proto)
1855 return;
1857 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1858 return;
1862 switch(m_spellInfo->Id)
1864 case 31789: // Righteous Defense (step 1)
1866 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1868 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1869 return;
1872 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1873 Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
1874 if (friendTarget)
1876 Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
1877 if (!player || !player->IsInSameRaidWith((Player*)m_caster))
1878 friendTarget = NULL;
1881 // non-standard cast requirement check
1882 if (!friendTarget || friendTarget->getAttackers().empty())
1884 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
1885 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1886 return;
1889 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1890 // Clear targets for eff 1
1891 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1892 ihit->effectMask &= ~(1<<1);
1894 // not empty (checked), copy
1895 Unit::AttackerSet attackers = friendTarget->getAttackers();
1897 // selected from list 3
1898 for(uint32 i = 0; i < std::min(size_t(3),attackers.size()); ++i)
1900 Unit::AttackerSet::iterator aItr = attackers.begin();
1901 std::advance(aItr, rand() % attackers.size());
1902 AddUnitTarget((*aItr), EFFECT_INDEX_1);
1903 attackers.erase(aItr);
1906 // now let next effect cast spell at each target.
1907 return;
1909 case 37877: // Blessing of Faith
1911 if (!unitTarget)
1912 return;
1914 uint32 spell_id = 0;
1915 switch(unitTarget->getClass())
1917 case CLASS_DRUID: spell_id = 37878; break;
1918 case CLASS_PALADIN: spell_id = 37879; break;
1919 case CLASS_PRIEST: spell_id = 37880; break;
1920 case CLASS_SHAMAN: spell_id = 37881; break;
1921 default: return; // ignore for not healing classes
1924 m_caster->CastSpell(m_caster, spell_id, true);
1925 return;
1928 break;
1929 case SPELLFAMILY_SHAMAN:
1930 // Cleansing Totem
1931 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
1933 if (unitTarget)
1934 m_caster->CastSpell(unitTarget, 52025, true);
1935 return;
1937 // Healing Stream Totem
1938 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
1940 if (unitTarget)
1942 if (Unit *owner = m_caster->GetOwner())
1944 // Restorative Totems
1945 Unit::AuraList const& mDummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
1946 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
1947 // only its have dummy with specific icon
1948 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (*i)->GetSpellProto()->SpellIconID == 338)
1949 damage += (*i)->GetModifier()->m_amount * damage / 100;
1951 // Glyph of Healing Stream Totem
1952 if (Aura *dummy = owner->GetDummyAura(55456))
1953 damage += dummy->GetModifier()->m_amount * damage / 100;
1955 m_caster->CastCustomSpell(unitTarget, 52042, &damage, NULL, NULL, true, 0, 0, m_originalCasterGUID);
1957 return;
1959 // Mana Spring Totem
1960 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
1962 if (!unitTarget || unitTarget->getPowerType()!=POWER_MANA)
1963 return;
1964 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1965 return;
1967 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
1969 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1970 return;
1971 // Glyph of Mana Tide
1972 if (Unit *owner = m_caster->GetOwner())
1973 if (Aura *dummy = owner->GetDummyAura(55441))
1974 damage+=dummy->GetModifier()->m_amount;
1975 // Regenerate 6% of Total Mana Every 3 secs
1976 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1977 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1978 return;
1980 // Lava Lash
1981 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1983 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1984 return;
1985 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1986 if (item)
1988 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1989 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1990 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1992 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1993 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
1994 (*itr)->GetCastItemGUID() == item->GetGUID())
1996 m_damage += m_damage * damage / 100;
1997 return;
2001 return;
2003 // Fire Nova
2004 if (m_spellInfo->SpellIconID == 33)
2006 // fire totems slot
2007 if (!m_caster->m_TotemSlot[0])
2008 return;
2010 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[0]);
2011 if (!totem)
2012 return;
2014 uint32 triggered_spell_id;
2015 switch(m_spellInfo->Id)
2017 case 1535: triggered_spell_id = 8349; break;
2018 case 8498: triggered_spell_id = 8502; break;
2019 case 8499: triggered_spell_id = 8503; break;
2020 case 11314: triggered_spell_id = 11306; break;
2021 case 11315: triggered_spell_id = 11307; break;
2022 case 25546: triggered_spell_id = 25535; break;
2023 case 25547: triggered_spell_id = 25537; break;
2024 case 61649: triggered_spell_id = 61650; break;
2025 case 61657: triggered_spell_id = 61654; break;
2026 default: return;
2029 totem->CastSpell(totem, triggered_spell_id, true, NULL, NULL, m_caster->GetGUID());
2031 // Fire Nova Visual
2032 totem->CastSpell(totem, 19823, true, NULL, NULL, m_caster->GetGUID());
2033 return;
2035 break;
2036 case SPELLFAMILY_DEATHKNIGHT:
2037 // Death Coil
2038 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
2040 if (m_caster->IsFriendlyTo(unitTarget))
2042 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
2043 return;
2045 int32 bp = int32(damage * 1.5f);
2046 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
2048 else
2050 int32 bp = damage;
2051 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
2053 return;
2055 // Hungering Cold
2056 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
2058 m_caster->CastSpell(m_caster, 51209, true);
2059 return;
2061 // Death Strike
2062 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
2064 uint32 count = 0;
2065 Unit::AuraMap const& auras = unitTarget->GetAuras();
2066 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2068 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
2069 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
2070 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
2072 ++count;
2073 // max. 15%
2074 if (count == 3)
2075 break;
2079 int32 bp = int32(count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100);
2080 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
2081 return;
2083 break;
2086 // pet auras
2087 if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id, eff_idx))
2089 m_caster->AddPetAura(petSpell);
2090 return;
2093 // Script based implementation. Must be used only for not good for implementation in core spell effects
2094 // So called only for not proccessed cases
2095 if (gameObjTarget)
2096 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, eff_idx, gameObjTarget);
2097 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
2098 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, eff_idx, (Creature*)unitTarget);
2099 else if (itemTarget)
2100 Script->EffectDummyItem(m_caster, m_spellInfo->Id, eff_idx, itemTarget);
2103 void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx)
2105 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2107 // normal case
2108 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2110 if(!spellInfo)
2112 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2113 return;
2116 int32 bp = damage;
2117 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
2120 void Spell::EffectTriggerRitualOfSummoning(SpellEffectIndex eff_idx)
2122 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2123 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2125 if(!spellInfo)
2127 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2128 return;
2131 finish();
2133 m_caster->CastSpell(unitTarget,spellInfo,false);
2136 void Spell::EffectForceCast(SpellEffectIndex eff_idx)
2138 if( !unitTarget )
2139 return;
2141 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2143 // normal case
2144 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2146 if(!spellInfo)
2148 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2149 return;
2152 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2155 void Spell::EffectTriggerSpell(SpellEffectIndex effIndex)
2157 // only unit case known
2158 if (!unitTarget)
2160 if(gameObjTarget || itemTarget)
2161 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
2162 return;
2165 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2167 // special cases
2168 switch(triggered_spell_id)
2170 // Vanish (not exist)
2171 case 18461:
2173 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2174 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2175 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2177 // if this spell is given to NPC it must handle rest by it's own AI
2178 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2179 return;
2181 // get highest rank of the Stealth spell
2182 uint32 spellId = 0;
2183 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2184 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2186 // only highest rank is shown in spell book, so simply check if shown in spell book
2187 if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
2188 continue;
2190 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2191 if (!spellInfo)
2192 continue;
2194 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2196 spellId = spellInfo->Id;
2197 break;
2201 // no Stealth spell found
2202 if (!spellId)
2203 return;
2205 // reset cooldown on it if needed
2206 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2207 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2209 m_caster->CastSpell(unitTarget, spellId, true);
2210 return;
2212 // just skip
2213 case 23770: // Sayge's Dark Fortune of *
2214 // not exist, common cooldown can be implemented in scripts if need.
2215 return;
2216 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2217 case 29284:
2219 // Brittle Armor
2220 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2221 if (!spell)
2222 return;
2224 for (uint32 j=0; j < spell->StackAmount; ++j)
2225 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2226 return;
2228 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2229 case 29286:
2231 // Mercurial Shield
2232 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2233 if (!spell)
2234 return;
2236 for (uint32 j=0; j < spell->StackAmount; ++j)
2237 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2238 return;
2240 // Righteous Defense
2241 case 31980:
2243 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2244 return;
2246 // Cloak of Shadows
2247 case 35729:
2249 Unit::AuraMap& Auras = unitTarget->GetAuras();
2250 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2252 // remove all harmful spells on you...
2253 if( // ignore positive and passive auras
2254 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2255 // ignore physical auras
2256 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2258 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2259 iter = Auras.begin();
2262 return;
2264 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2265 case 41967:
2267 if (Unit *pet = unitTarget->GetPet())
2268 pet->CastSpell(pet, 28305, true);
2269 return;
2273 // normal case
2274 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2275 if (!spellInfo)
2277 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2278 return;
2281 // select formal caster for triggered spell
2282 Unit* caster = m_caster;
2284 // some triggered spells require specific equipment
2285 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2287 // main hand weapon required
2288 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2290 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
2292 // skip spell if no weapon in slot or broken
2293 if (!item)
2294 return;
2296 // skip spell if weapon not fit to triggered spell
2297 if (!item->IsFitToSpellRequirements(spellInfo))
2298 return;
2301 // offhand hand weapon required
2302 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2304 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
2306 // skip spell if no weapon in slot or broken
2307 if (!item)
2308 return;
2310 // skip spell if weapon not fit to triggered spell
2311 if (!item->IsFitToSpellRequirements(spellInfo))
2312 return;
2315 else
2317 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2318 // so this just for speedup places in else
2319 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2322 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2325 void Spell::EffectTriggerMissileSpell(SpellEffectIndex effect_idx)
2327 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2329 // normal case
2330 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2332 if(!spellInfo)
2334 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2335 m_spellInfo->Id,effect_idx,triggered_spell_id);
2336 return;
2339 if (m_CastItem)
2340 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2342 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2345 void Spell::EffectJump(SpellEffectIndex eff_idx)
2347 if(m_caster->isInFlight())
2348 return;
2350 // Init dest coordinates
2351 float x,y,z,o;
2352 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2354 x = m_targets.m_destX;
2355 y = m_targets.m_destY;
2356 z = m_targets.m_destZ;
2358 if(m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_BEHIND_VICTIM)
2360 // explicit cast data from client or server-side cast
2361 // some spell at client send caster
2362 Unit* pTarget = NULL;
2363 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2364 pTarget = m_targets.getUnitTarget();
2365 else if(unitTarget->getVictim())
2366 pTarget = m_caster->getVictim();
2367 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2368 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2370 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2372 else
2373 o = m_caster->GetOrientation();
2375 else if(unitTarget)
2377 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2378 o = m_caster->GetOrientation();
2380 else if(gameObjTarget)
2382 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2383 o = m_caster->GetOrientation();
2385 else
2387 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2388 return;
2391 m_caster->NearTeleportTo(x, y, z, o, true);
2394 void Spell::EffectTeleportUnits(SpellEffectIndex eff_idx)
2396 if(!unitTarget || unitTarget->isInFlight())
2397 return;
2399 switch (m_spellInfo->EffectImplicitTargetB[eff_idx])
2401 case TARGET_INNKEEPER_COORDINATES:
2403 // Only players can teleport to innkeeper
2404 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2405 return;
2407 ((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
2408 return;
2410 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2411 case TARGET_TABLE_X_Y_Z_COORDINATES:
2413 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
2414 if(!st)
2416 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2417 return;
2420 if(st->target_mapId==unitTarget->GetMapId())
2421 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2422 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2423 ((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);
2424 break;
2426 case TARGET_BEHIND_VICTIM:
2428 Unit *pTarget = NULL;
2430 // explicit cast data from client or server-side cast
2431 // some spell at client send caster
2432 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2433 pTarget = m_targets.getUnitTarget();
2434 else if(unitTarget->getVictim())
2435 pTarget = unitTarget->getVictim();
2436 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2437 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2439 // Init dest coordinates
2440 float x = m_targets.m_destX;
2441 float y = m_targets.m_destY;
2442 float z = m_targets.m_destZ;
2443 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2444 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2445 return;
2447 default:
2449 // If not exist data for dest location - return
2450 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2452 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", eff_idx, m_spellInfo->EffectImplicitTargetB[eff_idx], m_spellInfo->Id );
2453 return;
2455 // Init dest coordinates
2456 float x = m_targets.m_destX;
2457 float y = m_targets.m_destY;
2458 float z = m_targets.m_destZ;
2459 float orientation = unitTarget->GetOrientation();
2460 // Teleport
2461 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2462 return;
2466 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2467 switch ( m_spellInfo->Id )
2469 // Dimensional Ripper - Everlook
2470 case 23442:
2472 int32 r = irand(0, 119);
2473 if ( r >= 70 ) // 7/12 success
2475 if ( r < 100 ) // 4/12 evil twin
2476 m_caster->CastSpell(m_caster, 23445, true);
2477 else // 1/12 fire
2478 m_caster->CastSpell(m_caster, 23449, true);
2480 return;
2482 // Ultrasafe Transporter: Toshley's Station
2483 case 36941:
2485 if ( roll_chance_i(50) ) // 50% success
2487 int32 rand_eff = urand(1, 7);
2488 switch ( rand_eff )
2490 case 1:
2491 // soul split - evil
2492 m_caster->CastSpell(m_caster, 36900, true);
2493 break;
2494 case 2:
2495 // soul split - good
2496 m_caster->CastSpell(m_caster, 36901, true);
2497 break;
2498 case 3:
2499 // Increase the size
2500 m_caster->CastSpell(m_caster, 36895, true);
2501 break;
2502 case 4:
2503 // Decrease the size
2504 m_caster->CastSpell(m_caster, 36893, true);
2505 break;
2506 case 5:
2507 // Transform
2509 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2510 m_caster->CastSpell(m_caster, 36897, true);
2511 else
2512 m_caster->CastSpell(m_caster, 36899, true);
2513 break;
2515 case 6:
2516 // chicken
2517 m_caster->CastSpell(m_caster, 36940, true);
2518 break;
2519 case 7:
2520 // evil twin
2521 m_caster->CastSpell(m_caster, 23445, true);
2522 break;
2525 return;
2527 // Dimensional Ripper - Area 52
2528 case 36890:
2530 if ( roll_chance_i(50) ) // 50% success
2532 int32 rand_eff = urand(1, 4);
2533 switch ( rand_eff )
2535 case 1:
2536 // soul split - evil
2537 m_caster->CastSpell(m_caster, 36900, true);
2538 break;
2539 case 2:
2540 // soul split - good
2541 m_caster->CastSpell(m_caster, 36901, true);
2542 break;
2543 case 3:
2544 // Increase the size
2545 m_caster->CastSpell(m_caster, 36895, true);
2546 break;
2547 case 4:
2548 // Transform
2550 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2551 m_caster->CastSpell(m_caster, 36897, true);
2552 else
2553 m_caster->CastSpell(m_caster, 36899, true);
2554 break;
2558 return;
2563 void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
2565 if(!unitTarget)
2566 return;
2568 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2569 if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) &&
2570 (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2571 return;
2573 Unit* caster = GetAffectiveCaster();
2574 if(!caster)
2575 return;
2577 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]);
2579 Aura* Aur = CreateAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, caster, m_CastItem);
2581 // Now Reduce spell duration using data received at spell hit
2582 int32 duration = Aur->GetAuraMaxDuration();
2583 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2584 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2585 Aur->setDiminishGroup(m_diminishGroup);
2587 // if Aura removed and deleted, do not continue.
2588 if(duration== 0 && !(Aur->IsPermanent()))
2590 delete Aur;
2591 return;
2594 if(duration != Aur->GetAuraMaxDuration())
2596 Aur->SetAuraMaxDuration(duration);
2597 Aur->SetAuraDuration(duration);
2600 unitTarget->AddAura(Aur);
2603 void Spell::EffectUnlearnSpecialization(SpellEffectIndex eff_idx)
2605 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2606 return;
2608 Player *_player = (Player*)unitTarget;
2609 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[eff_idx];
2611 _player->removeSpell(spellToUnlearn);
2613 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2616 void Spell::EffectPowerDrain(SpellEffectIndex eff_idx)
2618 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2619 return;
2621 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2623 if(!unitTarget)
2624 return;
2625 if(!unitTarget->isAlive())
2626 return;
2627 if(unitTarget->getPowerType() != drain_power)
2628 return;
2629 if(damage < 0)
2630 return;
2632 uint32 curPower = unitTarget->GetPower(drain_power);
2634 //add spell damage bonus
2635 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2637 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2638 uint32 power = damage;
2639 if (drain_power == POWER_MANA)
2640 power -= unitTarget->GetSpellCritDamageReduction(power);
2642 int32 new_damage;
2643 if(curPower < power)
2644 new_damage = curPower;
2645 else
2646 new_damage = power;
2648 unitTarget->ModifyPower(drain_power,-new_damage);
2650 // Don`t restore from self drain
2651 if(drain_power == POWER_MANA && m_caster != unitTarget)
2653 float manaMultiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2654 if(manaMultiplier==0)
2655 manaMultiplier = 1;
2657 if(Player *modOwner = m_caster->GetSpellModOwner())
2658 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2660 int32 gain = int32(new_damage * manaMultiplier);
2662 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2666 void Spell::EffectSendEvent(SpellEffectIndex effectIndex)
2669 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2671 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[effectIndex], m_spellInfo->Id);
2672 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject);
2675 void Spell::EffectPowerBurn(SpellEffectIndex eff_idx)
2677 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2678 return;
2680 Powers powertype = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2682 if (!unitTarget)
2683 return;
2684 if (!unitTarget->isAlive())
2685 return;
2686 if (unitTarget->getPowerType()!=powertype)
2687 return;
2688 if (damage < 0)
2689 return;
2691 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2692 if (m_spellInfo->ManaCostPercentage)
2694 int32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2695 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2696 if(damage > maxdamage)
2697 damage = maxdamage;
2700 int32 curPower = int32(unitTarget->GetPower(powertype));
2702 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2703 int32 power = damage;
2704 if (powertype == POWER_MANA)
2705 power -= unitTarget->GetSpellCritDamageReduction(power);
2707 int32 new_damage = (curPower < power) ? curPower : power;
2709 unitTarget->ModifyPower(powertype, -new_damage);
2710 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2712 if (Player *modOwner = m_caster->GetSpellModOwner())
2713 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2715 new_damage = int32(new_damage * multiplier);
2716 m_damage += new_damage;
2719 void Spell::EffectHeal(SpellEffectIndex /*eff_idx*/)
2721 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2723 // Try to get original caster
2724 Unit *caster = GetAffectiveCaster();
2725 if (!caster)
2726 return;
2728 int32 addhealth = damage;
2730 // Seal of Light proc
2731 if (m_spellInfo->Id == 20167)
2733 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
2734 int32 holy = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellInfo)) +
2735 caster->SpellBaseHealingBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
2736 addhealth += int32(ap * 0.15) + int32(holy * 15 / 100);
2738 // Vessel of the Naaru (Vial of the Sunwell trinket)
2739 else if (m_spellInfo->Id == 45064)
2741 // Amount of heal - depends from stacked Holy Energy
2742 int damageAmount = 0;
2743 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2744 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2745 if ((*i)->GetId() == 45062)
2746 damageAmount+=(*i)->GetModifier()->m_amount;
2747 if (damageAmount)
2748 m_caster->RemoveAurasDueToSpell(45062);
2750 addhealth += damageAmount;
2752 // Death Pact (percent heal)
2753 else if (m_spellInfo->Id==48743)
2754 addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
2755 // Swiftmend - consumes Regrowth or Rejuvenation
2756 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2758 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2759 // find most short by duration
2760 Aura *targetAura = NULL;
2761 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2763 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2764 // Regrowth or Rejuvenation 0x40 | 0x10
2765 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
2767 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2768 targetAura = *i;
2772 if (!targetAura)
2774 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
2775 return;
2777 int idx = 0;
2778 while(idx < 3)
2780 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2781 break;
2782 idx++;
2785 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2786 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2788 // Glyph of Swiftmend
2789 if (!caster->HasAura(54824))
2790 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2792 addhealth += tickheal * tickcount;
2794 else
2795 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2797 m_healing+=addhealth;
2801 void Spell::EffectHealPct(SpellEffectIndex /*eff_idx*/)
2803 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2805 // Try to get original caster
2806 Unit *caster = GetAffectiveCaster();
2807 if (!caster)
2808 return;
2810 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2811 if (Player* modOwner = m_caster->GetSpellModOwner())
2812 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2814 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2815 unitTarget->getHostileRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2819 void Spell::EffectHealMechanical(SpellEffectIndex /*eff_idx*/)
2821 // Mechanic creature type should be correctly checked by targetCreatureType field
2822 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2824 // Try to get original caster
2825 Unit *caster = GetAffectiveCaster();
2826 if (!caster)
2827 return;
2829 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, damage, HEAL);
2830 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2834 void Spell::EffectHealthLeech(SpellEffectIndex eff_idx)
2836 if (!unitTarget)
2837 return;
2838 if (!unitTarget->isAlive())
2839 return;
2841 if (damage < 0)
2842 return;
2844 sLog.outDebug("HealthLeech :%i", damage);
2846 uint32 curHealth = unitTarget->GetHealth();
2847 damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
2848 if ((int32)curHealth < damage)
2849 damage = curHealth;
2851 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2853 if (Player *modOwner = m_caster->GetSpellModOwner())
2854 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2856 int32 heal = int32(damage*multiplier);
2857 if (m_caster->isAlive())
2859 heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
2860 m_caster->DealHeal(m_caster, heal, m_spellInfo);
2864 void Spell::DoCreateItem(SpellEffectIndex eff_idx, uint32 itemtype)
2866 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2867 return;
2869 Player* player = (Player*)unitTarget;
2871 uint32 newitemid = itemtype;
2872 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype( newitemid );
2873 if(!pProto)
2875 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2876 return;
2879 // bg reward have some special in code work
2880 uint32 bgType = 0;
2881 switch(m_spellInfo->Id)
2883 case SPELL_AV_MARK_WINNER:
2884 case SPELL_AV_MARK_LOSER:
2885 bgType = BATTLEGROUND_AV;
2886 break;
2887 case SPELL_WS_MARK_WINNER:
2888 case SPELL_WS_MARK_LOSER:
2889 bgType = BATTLEGROUND_WS;
2890 break;
2891 case SPELL_AB_MARK_WINNER:
2892 case SPELL_AB_MARK_LOSER:
2893 bgType = BATTLEGROUND_AB;
2894 break;
2895 default:
2896 break;
2899 uint32 num_to_add;
2901 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2902 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2904 int32 basePoints = m_currentBasePoints[eff_idx];
2905 int32 randomPoints = m_spellInfo->EffectDieSides[eff_idx];
2906 if (randomPoints)
2907 num_to_add = basePoints + irand(1, randomPoints);
2908 else
2909 num_to_add = basePoints + 1;
2911 else if (pProto->MaxCount == 1)
2912 num_to_add = 1;
2913 else if(player->getLevel() >= m_spellInfo->spellLevel)
2915 int32 basePoints = m_currentBasePoints[eff_idx];
2916 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[eff_idx];
2917 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2919 else
2920 num_to_add = 2;
2922 if (num_to_add < 1)
2923 num_to_add = 1;
2924 if (num_to_add > pProto->GetMaxStackSize())
2925 num_to_add = pProto->GetMaxStackSize();
2927 // init items_count to 1, since 1 item will be created regardless of specialization
2928 int items_count=1;
2929 // the chance to create additional items
2930 float additionalCreateChance=0.0f;
2931 // the maximum number of created additional items
2932 uint8 additionalMaxNum=0;
2933 // get the chance and maximum number for creating extra items
2934 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2936 // roll with this chance till we roll not to create or we create the max num
2937 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2938 ++items_count;
2941 // really will be created more items
2942 num_to_add *= items_count;
2944 // can the player store the new item?
2945 ItemPosCountVec dest;
2946 uint32 no_space = 0;
2947 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2948 if( msg != EQUIP_ERR_OK )
2950 // convert to possible store amount
2951 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2952 num_to_add -= no_space;
2953 else
2955 // if not created by another reason from full inventory or unique items amount limitation
2956 player->SendEquipError( msg, NULL, NULL );
2957 return;
2961 if(num_to_add)
2963 // create the new item and store it
2964 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2966 // was it successful? return error if not
2967 if(!pItem)
2969 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2970 return;
2973 // set the "Crafted by ..." property of the item
2974 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2975 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
2977 // send info to the client
2978 if(pItem)
2979 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
2981 // we succeeded in creating at least one item, so a levelup is possible
2982 if(bgType == 0)
2983 player->UpdateCraftSkill(m_spellInfo->Id);
2986 // for battleground marks send by mail if not add all expected
2987 if(no_space > 0 && bgType)
2989 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
2990 bg->SendRewardMarkByMail(player, newitemid, no_space);
2994 void Spell::EffectCreateItem(SpellEffectIndex eff_idx)
2996 DoCreateItem(eff_idx,m_spellInfo->EffectItemType[eff_idx]);
2999 void Spell::EffectCreateItem2(SpellEffectIndex eff_idx)
3001 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3002 return;
3003 Player* player = (Player*)m_caster;
3005 uint32 item_id = m_spellInfo->EffectItemType[eff_idx];
3007 DoCreateItem(eff_idx, item_id);
3009 // special case: fake item replaced by generate using spell_loot_template
3010 if (IsLootCraftingSpell(m_spellInfo))
3012 if (!player->HasItemCount(item_id, 1))
3013 return;
3015 // remove reagent
3016 uint32 count = 1;
3017 player->DestroyItemCount(item_id, count, true);
3019 // create some random items
3020 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3024 void Spell::EffectCreateRandomItem(SpellEffectIndex /*eff_idx*/)
3026 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3027 return;
3028 Player* player = (Player*)m_caster;
3030 // create some random items
3031 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3034 void Spell::EffectPersistentAA(SpellEffectIndex eff_idx)
3036 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
3038 if (Player* modOwner = m_caster->GetSpellModOwner())
3039 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
3041 int32 duration = GetSpellDuration(m_spellInfo);
3042 DynamicObject* dynObj = new DynamicObject;
3043 if (!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3045 delete dynObj;
3046 return;
3048 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3049 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
3050 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
3051 m_caster->AddDynObject(dynObj);
3052 m_caster->GetMap()->Add(dynObj);
3055 void Spell::EffectEnergize(SpellEffectIndex eff_idx)
3057 if(!unitTarget)
3058 return;
3059 if(!unitTarget->isAlive())
3060 return;
3062 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3063 return;
3065 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3067 // Some level depends spells
3068 int level_multiplier = 0;
3069 int level_diff = 0;
3070 switch (m_spellInfo->Id)
3072 case 9512: // Restore Energy
3073 level_diff = m_caster->getLevel() - 40;
3074 level_multiplier = 2;
3075 break;
3076 case 24571: // Blood Fury
3077 level_diff = m_caster->getLevel() - 60;
3078 level_multiplier = 10;
3079 break;
3080 case 24532: // Burst of Energy
3081 level_diff = m_caster->getLevel() - 60;
3082 level_multiplier = 4;
3083 break;
3084 case 31930: // Judgements of the Wise
3085 case 48542: // Revitalize (mana restore case)
3086 case 63375: // Improved Stormstrike
3087 damage = damage * unitTarget->GetCreateMana() / 100;
3088 break;
3089 default:
3090 break;
3093 if (level_diff > 0)
3094 damage -= level_multiplier * level_diff;
3096 if(damage < 0)
3097 return;
3099 if(unitTarget->GetMaxPower(power) == 0)
3100 return;
3102 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
3104 // Mad Alchemist's Potion
3105 if (m_spellInfo->Id == 45051)
3107 // find elixirs on target
3108 uint32 elixir_mask = 0;
3109 Unit::AuraMap& Auras = unitTarget->GetAuras();
3110 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3112 uint32 spell_id = itr->second->GetId();
3113 if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
3114 elixir_mask |= mask;
3117 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3118 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
3120 // get all available elixirs by mask and spell level
3121 std::vector<uint32> elixirs;
3122 SpellElixirMap const& m_spellElixirs = sSpellMgr.GetSpellElixirMap();
3123 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
3125 if (itr->second & elixir_mask)
3127 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
3128 continue;
3130 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
3131 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
3132 continue;
3134 elixirs.push_back(itr->first);
3138 if (!elixirs.empty())
3140 // cast random elixir on target
3141 uint32 rand_spell = urand(0,elixirs.size()-1);
3142 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
3147 void Spell::EffectEnergisePct(SpellEffectIndex eff_idx)
3149 if (!unitTarget)
3150 return;
3151 if (!unitTarget->isAlive())
3152 return;
3154 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3155 return;
3157 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3159 uint32 maxPower = unitTarget->GetMaxPower(power);
3160 if (maxPower == 0)
3161 return;
3163 uint32 gain = damage * maxPower / 100;
3164 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
3167 void Spell::SendLoot(uint64 guid, LootType loottype)
3169 if (gameObjTarget)
3171 switch (gameObjTarget->GetGoType())
3173 case GAMEOBJECT_TYPE_DOOR:
3174 case GAMEOBJECT_TYPE_BUTTON:
3175 case GAMEOBJECT_TYPE_QUESTGIVER:
3176 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3177 case GAMEOBJECT_TYPE_GOOBER:
3178 gameObjTarget->Use(m_caster);
3179 return;
3181 case GAMEOBJECT_TYPE_CHEST:
3182 gameObjTarget->Use(m_caster);
3183 // Don't return, let loots been taken
3184 break;
3186 default:
3187 sLog.outError("Spell::SendLoot unhandled GameObject type %u (entry %u).", gameObjTarget->GetGoType(), gameObjTarget->GetEntry());
3188 return;
3192 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3193 return;
3195 // Send loot
3196 ((Player*)m_caster)->SendLoot(guid, loottype);
3199 void Spell::EffectOpenLock(SpellEffectIndex eff_idx)
3201 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3203 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3204 return;
3207 Player* player = (Player*)m_caster;
3209 uint32 lockId = 0;
3210 uint64 guid = 0;
3212 // Get lockId
3213 if (gameObjTarget)
3215 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3216 // Arathi Basin banner opening !
3217 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3218 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3220 //CanUseBattleGroundObject() already called in CheckCast()
3221 // in battleground check
3222 if (BattleGround *bg = player->GetBattleGround())
3224 // check if it's correct bg
3225 if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
3226 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3227 return;
3230 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3232 //CanUseBattleGroundObject() already called in CheckCast()
3233 // in battleground check
3234 if (BattleGround *bg = player->GetBattleGround())
3236 if (bg->GetTypeID() == BATTLEGROUND_EY)
3237 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3238 return;
3241 lockId = goInfo->GetLockId();
3242 guid = gameObjTarget->GetGUID();
3244 else if (itemTarget)
3246 lockId = itemTarget->GetProto()->LockID;
3247 guid = itemTarget->GetGUID();
3249 else
3251 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3252 return;
3255 SkillType skillId = SKILL_NONE;
3256 int32 reqSkillValue = 0;
3257 int32 skillValue;
3259 SpellCastResult res = CanOpenLock(eff_idx, lockId, skillId, reqSkillValue, skillValue);
3260 if (res != SPELL_CAST_OK)
3262 SendCastResult(res);
3263 return;
3266 SendLoot(guid, LOOT_SKINNING);
3268 // not allow use skill grow at item base open
3269 if (!m_CastItem && skillId != SKILL_NONE)
3271 // update skill if really known
3272 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3274 if (gameObjTarget)
3276 // Allow one skill-up until respawned
3277 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3278 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3279 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3281 else if (itemTarget)
3283 // Do one skill-up
3284 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3290 void Spell::EffectSummonChangeItem(SpellEffectIndex eff_idx)
3292 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3293 return;
3295 Player *player = (Player*)m_caster;
3297 // applied only to using item
3298 if (!m_CastItem)
3299 return;
3301 // ... only to item in own inventory/bank/equip_slot
3302 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3303 return;
3305 uint32 newitemid = m_spellInfo->EffectItemType[eff_idx];
3306 if (!newitemid)
3307 return;
3309 uint16 pos = m_CastItem->GetPos();
3311 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3312 if (!pNewItem)
3313 return;
3315 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3317 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3318 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3321 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3323 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3324 player->DurabilityLoss(pNewItem, loosePercent);
3327 if (player->IsInventoryPos(pos))
3329 ItemPosCountVec dest;
3330 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3331 if (msg == EQUIP_ERR_OK)
3333 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3335 // prevent crash at access and unexpected charges counting with item update queue corrupt
3336 if (m_CastItem==m_targets.getItemTarget())
3337 m_targets.setItemTarget(NULL);
3339 m_CastItem = NULL;
3341 player->StoreItem( dest, pNewItem, true);
3342 return;
3345 else if (player->IsBankPos (pos))
3347 ItemPosCountVec dest;
3348 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3349 if (msg == EQUIP_ERR_OK)
3351 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3353 // prevent crash at access and unexpected charges counting with item update queue corrupt
3354 if (m_CastItem==m_targets.getItemTarget())
3355 m_targets.setItemTarget(NULL);
3357 m_CastItem = NULL;
3359 player->BankItem( dest, pNewItem, true);
3360 return;
3363 else if (player->IsEquipmentPos (pos))
3365 uint16 dest;
3366 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3367 if (msg == EQUIP_ERR_OK)
3369 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3371 // prevent crash at access and unexpected charges counting with item update queue corrupt
3372 if (m_CastItem==m_targets.getItemTarget())
3373 m_targets.setItemTarget(NULL);
3375 m_CastItem = NULL;
3377 player->EquipItem( dest, pNewItem, true);
3378 player->AutoUnequipOffhandIfNeed();
3379 return;
3383 // fail
3384 delete pNewItem;
3387 void Spell::EffectProficiency(SpellEffectIndex /*eff_idx*/)
3389 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3390 return;
3391 Player *p_target = (Player*)unitTarget;
3393 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3394 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3396 p_target->AddWeaponProficiency(subClassMask);
3397 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3399 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3401 p_target->AddArmorProficiency(subClassMask);
3402 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3406 void Spell::EffectApplyAreaAura(SpellEffectIndex eff_idx)
3408 if (!unitTarget)
3409 return;
3410 if (!unitTarget->isAlive())
3411 return;
3413 AreaAura* Aur = new AreaAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, m_caster, m_CastItem);
3414 unitTarget->AddAura(Aur);
3417 void Spell::EffectSummonType(SpellEffectIndex eff_idx)
3419 uint32 prop_id = m_spellInfo->EffectMiscValueB[eff_idx];
3420 SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
3421 if(!summon_prop)
3423 sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3424 return;
3427 switch(summon_prop->Group)
3429 // faction handled later on, or loaded from template
3430 case SUMMON_PROP_GROUP_WILD:
3431 case SUMMON_PROP_GROUP_FRIENDLY:
3433 switch(summon_prop->Type)
3435 case SUMMON_PROP_TYPE_OTHER:
3437 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3438 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3439 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3440 if(prop_id == 121 || prop_id == 647)
3441 DoSummonTotem(eff_idx);
3442 else
3443 DoSummonWild(eff_idx, summon_prop->FactionId);
3444 break;
3446 case SUMMON_PROP_TYPE_SUMMON:
3447 case SUMMON_PROP_TYPE_GUARDIAN:
3448 case SUMMON_PROP_TYPE_ARMY:
3449 case SUMMON_PROP_TYPE_DK:
3450 case SUMMON_PROP_TYPE_CONSTRUCT:
3452 // JC golems - 32804, etc -- fits much better totem AI
3453 if(m_spellInfo->SpellIconID == 2056)
3454 DoSummonTotem(eff_idx);
3455 if(prop_id == 832) // scrapbot
3456 DoSummonWild(eff_idx, summon_prop->FactionId);
3457 else
3458 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3459 break;
3461 case SUMMON_PROP_TYPE_TOTEM:
3462 DoSummonTotem(eff_idx, summon_prop->Slot);
3463 break;
3464 case SUMMON_PROP_TYPE_CRITTER:
3465 DoSummonCritter(eff_idx, summon_prop->FactionId);
3466 break;
3467 case SUMMON_PROP_TYPE_PHASING:
3468 case SUMMON_PROP_TYPE_LIGHTWELL:
3469 case SUMMON_PROP_TYPE_REPAIR_BOT:
3470 DoSummonWild(eff_idx, summon_prop->FactionId);
3471 break;
3472 case SUMMON_PROP_TYPE_SIEGE_VEH:
3473 case SUMMON_PROP_TYPE_DRAKE_VEH:
3474 // TODO
3475 // EffectSummonVehicle(i);
3476 break;
3477 default:
3478 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
3479 break;
3481 break;
3483 case SUMMON_PROP_GROUP_PETS:
3485 // FIXME : multiple summons - not yet supported as pet
3486 //1562 - force of nature - sid 33831
3487 //1161 - feral spirit - sid 51533
3488 if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
3489 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3490 else
3491 DoSummon(eff_idx);
3492 break;
3494 case SUMMON_PROP_GROUP_CONTROLLABLE:
3496 // no type here
3497 // maybe wrong - but thats the handler currently used for those
3498 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3499 break;
3501 case SUMMON_PROP_GROUP_VEHICLE:
3503 // TODO
3504 // EffectSummonVehicle(i);
3505 break;
3507 default:
3508 sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
3509 break;
3513 void Spell::DoSummon(SpellEffectIndex eff_idx)
3515 if (m_caster->GetPetGUID())
3516 return;
3518 if (!unitTarget)
3519 return;
3520 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
3521 if (!pet_entry)
3522 return;
3523 uint32 level = m_caster->getLevel();
3524 Pet* spawnCreature = new Pet(SUMMON_PET);
3526 int32 duration = GetSpellDuration(m_spellInfo);
3527 if(Player* modOwner = m_caster->GetSpellModOwner())
3528 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3530 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3532 // Summon in dest location
3533 float x, y, z;
3534 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3536 x = m_targets.m_destX;
3537 y = m_targets.m_destY;
3538 z = m_targets.m_destZ;
3539 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3542 // set timer for unsummon
3543 if (duration > 0)
3544 spawnCreature->SetDuration(duration);
3546 return;
3549 Map *map = m_caster->GetMap();
3550 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3551 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3552 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
3554 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[eff_idx]);
3555 delete spawnCreature;
3556 return;
3559 // Summon in dest location
3560 float x, y, z;
3561 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3563 x = m_targets.m_destX;
3564 y = m_targets.m_destY;
3565 z = m_targets.m_destZ;
3567 else
3568 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3570 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3572 if (!spawnCreature->IsPositionValid())
3574 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3575 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3576 delete spawnCreature;
3577 return;
3580 // set timer for unsummon
3581 if (duration > 0)
3582 spawnCreature->SetDuration(duration);
3584 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3585 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3586 spawnCreature->setPowerType(POWER_MANA);
3587 spawnCreature->setFaction(m_caster->getFaction());
3588 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3589 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3590 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3591 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3592 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3593 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3594 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3595 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3597 spawnCreature->InitStatsForLevel(level, m_caster);
3599 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3601 spawnCreature->UpdateWalkMode(m_caster);
3603 spawnCreature->AIM_Initialize();
3604 spawnCreature->InitPetCreateSpells();
3605 spawnCreature->InitLevelupSpellsForLevel();
3606 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3607 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3609 std::string name = m_caster->GetName();
3610 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3611 spawnCreature->SetName( name );
3613 map->Add((Creature*)spawnCreature);
3615 m_caster->SetPet(spawnCreature);
3617 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3619 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3620 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3621 ((Player*)m_caster)->PetSpellInitialize();
3625 void Spell::EffectLearnSpell(SpellEffectIndex eff_idx)
3627 if (!unitTarget)
3628 return;
3630 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3632 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3633 EffectLearnPetSpell(eff_idx);
3635 return;
3638 Player *player = (Player*)unitTarget;
3640 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[eff_idx];
3641 player->learnSpell(spellToLearn,false);
3643 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3646 void Spell::EffectDispel(SpellEffectIndex eff_idx)
3648 if (!unitTarget)
3649 return;
3651 // Fill possible dispell list
3652 std::vector <Aura *> dispel_list;
3654 // Create dispel mask by dispel type
3655 uint32 dispel_type = m_spellInfo->EffectMiscValue[eff_idx];
3656 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3657 Unit::AuraMap const& auras = unitTarget->GetAuras();
3658 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3660 Aura *aur = (*itr).second;
3661 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3663 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3665 bool positive = true;
3666 if (!aur->IsPositive())
3667 positive = false;
3668 else
3669 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3671 // do not remove positive auras if friendly target
3672 // negative auras if non-friendly target
3673 if (positive == unitTarget->IsFriendlyTo(m_caster))
3674 continue;
3676 // Add aura to dispel list (all stack cases)
3677 for(int k = 0; k < aur->GetStackAmount(); ++k)
3678 dispel_list.push_back(aur);
3681 // Ok if exist some buffs for dispel try dispel it
3682 if (!dispel_list.empty())
3684 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3685 std::list < uint32 > fail_list; // spell_id
3687 // some spells have effect value = 0 and all from its by meaning expect 1
3688 if(!damage)
3689 damage = 1;
3691 // Dispell N = damage buffs (or while exist buffs for dispel)
3692 for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
3694 // Random select buff for dispel
3695 std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
3696 std::advance(dispel_itr,urand(0, dispel_list.size()-1));
3698 Aura *aur = *dispel_itr;
3700 // remove entry from dispel_list
3701 dispel_list.erase(dispel_itr);
3703 SpellEntry const* spellInfo = aur->GetSpellProto();
3704 // Base dispel chance
3705 // TODO: possible chance depend from spell level??
3706 int32 miss_chance = 0;
3707 // Apply dispel mod from aura caster
3708 if (Unit *caster = aur->GetCaster())
3710 if ( Player* modOwner = caster->GetSpellModOwner() )
3711 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3713 // Try dispel
3714 if (roll_chance_i(miss_chance))
3715 fail_list.push_back(spellInfo->Id);
3716 else
3717 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3719 // Send success log and really remove auras
3720 if (!success_list.empty())
3722 int32 count = success_list.size();
3723 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3724 data.append(unitTarget->GetPackGUID()); // Victim GUID
3725 data.append(m_caster->GetPackGUID()); // Caster GUID
3726 data << uint32(m_spellInfo->Id); // Dispel spell id
3727 data << uint8(0); // not used
3728 data << uint32(count); // count
3729 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3731 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3732 data << uint32(spellInfo->Id); // Spell Id
3733 data << uint8(0); // 0 - dispeled !=0 cleansed
3734 unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3736 m_caster->SendMessageToSet(&data, true);
3738 // On success dispel
3739 // Devour Magic
3740 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3742 int32 heal_amount = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
3743 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
3746 // Send fail log to client
3747 if (!fail_list.empty())
3749 // Failed to dispell
3750 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3751 data << uint64(m_caster->GetGUID()); // Caster GUID
3752 data << uint64(unitTarget->GetGUID()); // Victim GUID
3753 data << uint32(m_spellInfo->Id); // Dispell spell id
3754 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3755 data << uint32(*j); // Spell Id
3756 m_caster->SendMessageToSet(&data, true);
3761 void Spell::EffectDualWield(SpellEffectIndex /*eff_idx*/)
3763 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3764 ((Player*)unitTarget)->SetCanDualWield(true);
3767 void Spell::EffectPull(SpellEffectIndex /*eff_idx*/)
3769 // TODO: create a proper pull towards distract spell center for distract
3770 sLog.outDebug("WORLD: Spell Effect DUMMY");
3773 void Spell::EffectDistract(SpellEffectIndex /*eff_idx*/)
3775 // Check for possible target
3776 if (!unitTarget || unitTarget->isInCombat())
3777 return;
3779 // target must be OK to do this
3780 if( unitTarget->hasUnitState(UNIT_STAT_CAN_NOT_REACT) )
3781 return;
3783 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3785 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3787 // For players just turn them
3788 WorldPacket data;
3789 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3790 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3791 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3793 else
3795 // Set creature Distracted, Stop it, And turn it
3796 unitTarget->SetOrientation(angle);
3797 unitTarget->StopMoving();
3798 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
3802 void Spell::EffectPickPocket(SpellEffectIndex /*eff_idx*/)
3804 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3805 return;
3807 // victim must be creature and attackable
3808 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
3809 return;
3811 // victim have to be alive and humanoid or undead
3812 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3814 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3816 if (chance > irand(0, 19))
3818 // Stealing successful
3819 //sLog.outDebug("Sending loot from pickpocket");
3820 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3822 else
3824 // Reveal action + get attack
3825 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3826 if (((Creature*)unitTarget)->AI())
3827 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3832 void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
3834 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3835 return;
3837 int32 duration = GetSpellDuration(m_spellInfo);
3838 DynamicObject* dynObj = new DynamicObject;
3840 // set radius to 0: spell not expected to work as persistent aura
3841 if(!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
3843 delete dynObj;
3844 return;
3846 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3847 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3848 m_caster->AddDynObject(dynObj);
3849 m_caster->GetMap()->Add(dynObj);
3850 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3853 void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)
3855 uint32 creature_entry = m_spellInfo->EffectMiscValue[eff_idx];
3856 if (!creature_entry)
3857 return;
3859 uint32 level = m_caster->getLevel();
3861 // level of creature summoned using engineering item based at engineering skill level
3862 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3864 ItemPrototype const *proto = m_CastItem->GetProto();
3865 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3867 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3868 if (skill202)
3869 level = skill202/5;
3873 // select center of summon position
3874 float center_x = m_targets.m_destX;
3875 float center_y = m_targets.m_destY;
3876 float center_z = m_targets.m_destZ;
3878 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
3879 int32 duration = GetSpellDuration(m_spellInfo);
3880 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3882 int32 amount = damage > 0 ? damage : 1;
3884 for(int32 count = 0; count < amount; ++count)
3886 float px, py, pz;
3887 // If dest location if present
3888 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3890 // Summon 1 unit in dest location
3891 if (count == 0)
3893 px = m_targets.m_destX;
3894 py = m_targets.m_destY;
3895 pz = m_targets.m_destZ;
3897 // Summon in random point all other units if location present
3898 else
3899 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3901 // Summon if dest location not present near caster
3902 else
3903 m_caster->GetClosePoint(px, py, pz, 3.0f);
3905 if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
3907 summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3908 summon->SetCreatorGUID(m_caster->GetGUID());
3910 if(forceFaction)
3911 summon->setFaction(forceFaction);
3916 void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction)
3918 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
3919 if (!pet_entry)
3920 return;
3922 // in another case summon new
3923 uint32 level = m_caster->getLevel();
3925 // level of pet summoned using engineering item based at engineering skill level
3926 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
3928 ItemPrototype const *proto = m_CastItem->GetProto();
3929 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3931 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3932 if (skill202)
3934 level = skill202 / 5;
3939 // select center of summon position
3940 float center_x = m_targets.m_destX;
3941 float center_y = m_targets.m_destY;
3942 float center_z = m_targets.m_destZ;
3944 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
3945 int32 duration = GetSpellDuration(m_spellInfo);
3946 if(Player* modOwner = m_caster->GetSpellModOwner())
3947 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3949 int32 amount = damage > 0 ? damage : 1;
3951 for(int32 count = 0; count < amount; ++count)
3953 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3955 Map *map = m_caster->GetMap();
3956 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3957 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3958 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
3960 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[eff_idx]);
3961 delete spawnCreature;
3962 return;
3965 float px, py, pz;
3966 // If dest location if present
3967 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3969 // Summon 1 unit in dest location
3970 if (count == 0)
3972 px = m_targets.m_destX;
3973 py = m_targets.m_destY;
3974 pz = m_targets.m_destZ;
3976 // Summon in random point all other units if location present
3977 else
3978 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3980 // Summon if dest location not present near caster
3981 else
3982 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
3984 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
3986 if (!spawnCreature->IsPositionValid())
3988 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3989 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3990 delete spawnCreature;
3991 return;
3994 if (duration > 0)
3995 spawnCreature->SetDuration(duration);
3997 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3998 spawnCreature->setPowerType(POWER_MANA);
3999 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
4000 spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
4001 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
4002 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4003 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
4004 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
4005 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4007 spawnCreature->InitStatsForLevel(level, m_caster);
4008 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
4010 spawnCreature->AIM_Initialize();
4012 m_caster->AddGuardian(spawnCreature);
4014 map->Add((Creature*)spawnCreature);
4018 void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx)
4020 if (!unitTarget)
4021 return;
4023 if (unitTarget->isInFlight())
4024 return;
4026 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4028 float fx, fy, fz;
4029 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
4031 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
4034 void Spell::EffectLearnSkill(SpellEffectIndex eff_idx)
4036 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4037 return;
4039 if (damage < 0)
4040 return;
4042 uint32 skillid = m_spellInfo->EffectMiscValue[eff_idx];
4043 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
4044 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4047 void Spell::EffectAddHonor(SpellEffectIndex /*eff_idx*/)
4049 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4050 return;
4052 // not scale value for item based reward (/10 value expected)
4053 if (m_CastItem)
4055 ((Player*)unitTarget)->RewardHonor(NULL, 1, float(damage / 10));
4056 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
4057 return;
4060 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4061 if (damage <= 50)
4063 float honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
4064 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
4065 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
4067 else
4069 //maybe we have correct honor_gain in damage already
4070 ((Player*)unitTarget)->RewardHonor(NULL, 1, (float)damage);
4071 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
4075 void Spell::EffectTradeSkill(SpellEffectIndex /*eff_idx*/)
4077 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4078 return;
4079 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4080 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4081 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4084 void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx)
4086 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4087 return;
4088 if (!itemTarget)
4089 return;
4091 Player* p_caster = (Player*)m_caster;
4093 // not grow at item use at item case
4094 p_caster->UpdateCraftSkill(m_spellInfo->Id);
4096 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4097 if (!enchant_id)
4098 return;
4100 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4101 if (!pEnchant)
4102 return;
4104 // item can be in trade slot and have owner diff. from caster
4105 Player* item_owner = itemTarget->GetOwner();
4106 if (!item_owner)
4107 return;
4109 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4111 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4112 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4113 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4114 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4117 // remove old enchanting before applying new if equipped
4118 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
4120 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4122 // add new enchanting if equipped
4123 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
4125 // update trade window for show enchantment for caster in trade window
4126 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4127 p_caster->GetSession()->SendUpdateTrade();
4130 void Spell::EffectEnchantItemPrismatic(SpellEffectIndex eff_idx)
4132 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4133 return;
4134 if (!itemTarget)
4135 return;
4137 Player* p_caster = (Player*)m_caster;
4139 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4140 if (!enchant_id)
4141 return;
4143 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4144 if (!pEnchant)
4145 return;
4147 // support only enchantings with add socket in this slot
4149 bool add_socket = false;
4150 for(int i = 0; i < 3; ++i)
4152 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
4154 add_socket = true;
4155 break;
4158 if (!add_socket)
4160 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.",
4161 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
4162 return;
4166 // item can be in trade slot and have owner diff. from caster
4167 Player* item_owner = itemTarget->GetOwner();
4168 if (!item_owner)
4169 return;
4171 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4173 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4174 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4175 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4176 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4179 // remove old enchanting before applying new if equipped
4180 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4182 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4184 // add new enchanting if equipped
4185 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4187 // update trade window for show enchantment for caster in trade window
4188 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4189 p_caster->GetSession()->SendUpdateTrade();
4192 void Spell::EffectEnchantItemTmp(SpellEffectIndex eff_idx)
4194 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4195 return;
4197 Player* p_caster = (Player*)m_caster;
4199 // Rockbiter Weapon apply to both weapon
4200 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000))
4202 uint32 spell_id = 0;
4204 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4205 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4206 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4207 switch(damage)
4209 // Rank 1
4210 case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4211 // Rank 2
4212 case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
4213 case 5: spell_id = 36751; break; // 20%
4214 // Rank 3
4215 case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
4216 case 7: spell_id = 36755; break; // 20%
4217 // Rank 4
4218 case 9: spell_id = 36761; break; // 0% [ 7% == 6]
4219 case 10: spell_id = 36758; break; // 14%
4220 case 11: spell_id = 36760; break; // 20%
4221 default:
4222 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
4223 return;
4227 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
4228 if (!spellInfo)
4230 sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
4231 return;
4234 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
4236 if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
4238 if (item->IsFitToSpellRequirements(m_spellInfo))
4240 Spell *spell = new Spell(m_caster, spellInfo, true);
4241 SpellCastTargets targets;
4242 targets.setItemTarget( item );
4243 spell->prepare(&targets);
4247 return;
4250 if (!itemTarget)
4251 return;
4253 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4255 if (!enchant_id)
4257 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,eff_idx);
4258 return;
4261 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4262 if(!pEnchant)
4264 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,eff_idx,enchant_id);
4265 return;
4268 // select enchantment duration
4269 uint32 duration;
4271 // rogue family enchantments exception by duration
4272 if(m_spellInfo->Id == 38615)
4273 duration = 1800; // 30 mins
4274 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4275 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4276 duration = 3600; // 1 hour
4277 // shaman family enchantments
4278 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4279 duration = 1800; // 30 mins
4280 // other cases with this SpellVisual already selected
4281 else if(m_spellInfo->SpellVisual[0] == 215)
4282 duration = 1800; // 30 mins
4283 // some fishing pole bonuses
4284 else if(m_spellInfo->SpellVisual[0] == 563)
4285 duration = 600; // 10 mins
4286 // shaman rockbiter enchantments
4287 else if(m_spellInfo->SpellVisual[0] == 0)
4288 duration = 1800; // 30 mins
4289 else if(m_spellInfo->Id == 29702)
4290 duration = 300; // 5 mins
4291 else if(m_spellInfo->Id == 37360)
4292 duration = 300; // 5 mins
4293 // default case
4294 else
4295 duration = 3600; // 1 hour
4297 // item can be in trade slot and have owner diff. from caster
4298 Player* item_owner = itemTarget->GetOwner();
4299 if(!item_owner)
4300 return;
4302 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4304 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4305 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4306 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4307 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4310 // remove old enchanting before applying new if equipped
4311 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4313 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4315 // add new enchanting if equipped
4316 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4318 // update trade window for show enchantment for caster in trade window
4319 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4320 p_caster->GetSession()->SendUpdateTrade();
4323 void Spell::EffectTameCreature(SpellEffectIndex /*eff_idx*/)
4325 // Caster must be player, checked in Spell::CheckCast
4326 // Spell can be triggered, we need to check original caster prior to caster
4327 Player* plr = (Player*)GetAffectiveCaster();
4329 Creature* creatureTarget = (Creature*)unitTarget;
4331 // cast finish successfully
4332 //SendChannelUpdate(0);
4333 finish();
4335 Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4336 if(!pet) // in versy specific state like near world end/etc.
4337 return;
4339 // "kill" original creature
4340 creatureTarget->ForcedDespawn();
4342 uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel();
4344 // prepare visual effect for levelup
4345 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4347 // add to world
4348 pet->GetMap()->Add((Creature*)pet);
4350 // visual effect for levelup
4351 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4353 // caster have pet now
4354 plr->SetPet(pet);
4356 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4357 plr->PetSpellInitialize();
4360 void Spell::EffectSummonPet(SpellEffectIndex eff_idx)
4362 uint32 petentry = m_spellInfo->EffectMiscValue[eff_idx];
4364 Pet *OldSummon = m_caster->GetPet();
4366 // if pet requested type already exist
4367 if( OldSummon )
4369 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4371 // pet in corpse state can't be summoned
4372 if( OldSummon->isDead() )
4373 return;
4375 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4377 float px, py, pz;
4378 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4380 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4381 m_caster->GetMap()->Add((Creature*)OldSummon);
4383 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4385 ((Player*)m_caster)->PetSpellInitialize();
4387 return;
4390 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4391 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4392 else
4393 return;
4396 Pet* NewSummon = new Pet;
4398 // petentry==0 for hunter "call pet" (current pet summoned if any)
4399 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
4401 if(NewSummon->getPetType() == SUMMON_PET)
4403 // Remove Demonic Sacrifice auras (known pet)
4404 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4405 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4407 if((*itr)->GetModifier()->m_miscvalue == 2228)
4409 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4410 itr = auraClassScripts.begin();
4412 else
4413 ++itr;
4417 return;
4420 // not error in case fail hunter call pet
4421 if(!petentry)
4423 delete NewSummon;
4424 return;
4427 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4429 if(!cInfo)
4431 sLog.outError("EffectSummonPet: creature entry %u not found.", petentry);
4432 delete NewSummon;
4433 return;
4436 Map *map = m_caster->GetMap();
4437 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4438 if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4439 petentry, pet_number))
4441 delete NewSummon;
4442 return;
4445 float px, py, pz;
4446 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4448 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4450 if(!NewSummon->IsPositionValid())
4452 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4453 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4454 delete NewSummon;
4455 return;
4458 uint32 petlevel = m_caster->getLevel();
4459 NewSummon->setPetType(SUMMON_PET);
4461 uint32 faction = m_caster->getFaction();
4462 if(m_caster->GetTypeId() == TYPEID_UNIT)
4464 if ( ((Creature*)m_caster)->isTotem() )
4465 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4466 else
4467 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4470 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4471 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4472 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4473 NewSummon->setFaction(faction);
4474 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4475 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4476 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL)));
4477 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4478 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4479 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4481 NewSummon->UpdateWalkMode(m_caster);
4483 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4484 // this enables pet details window (Shift+P)
4486 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4487 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4488 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
4490 if(m_caster->IsPvP())
4491 NewSummon->SetPvP(true);
4493 if(m_caster->IsFFAPvP())
4494 NewSummon->SetFFAPvP(true);
4496 NewSummon->InitStatsForLevel(petlevel, m_caster);
4497 NewSummon->InitPetCreateSpells();
4498 NewSummon->InitLevelupSpellsForLevel();
4499 NewSummon->InitTalentForLevel();
4501 if(NewSummon->getPetType() == SUMMON_PET)
4503 // Remove Demonic Sacrifice auras (new pet)
4504 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4505 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4507 if((*itr)->GetModifier()->m_miscvalue == 2228)
4509 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4510 itr = auraClassScripts.begin();
4512 else
4513 ++itr;
4516 // generate new name for summon pet
4517 std::string new_name = sObjectMgr.GeneratePetName(petentry);
4518 if(!new_name.empty())
4519 NewSummon->SetName(new_name);
4521 else if(NewSummon->getPetType() == HUNTER_PET)
4523 NewSummon->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
4524 NewSummon->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED);
4527 NewSummon->AIM_Initialize();
4528 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4529 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4531 map->Add((Creature*)NewSummon);
4533 m_caster->SetPet(NewSummon);
4534 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4536 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4538 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4539 ((Player*)m_caster)->PetSpellInitialize();
4543 void Spell::EffectLearnPetSpell(SpellEffectIndex eff_idx)
4545 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4546 return;
4548 Player *_player = (Player*)m_caster;
4550 Pet *pet = _player->GetPet();
4551 if(!pet)
4552 return;
4553 if(!pet->isAlive())
4554 return;
4556 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[eff_idx]);
4557 if(!learn_spellproto)
4558 return;
4560 pet->learnSpell(learn_spellproto->Id);
4562 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4563 _player->PetSpellInitialize();
4566 void Spell::EffectTaunt(SpellEffectIndex /*eff_idx*/)
4568 if (!unitTarget)
4569 return;
4571 // this effect use before aura Taunt apply for prevent taunt already attacking target
4572 // for spell as marked "non effective at already attacking target"
4573 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4575 if (unitTarget->getVictim()==m_caster)
4577 SendCastResult(SPELL_FAILED_DONT_REPORT);
4578 return;
4582 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4583 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4584 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4587 void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
4589 if(!unitTarget)
4590 return;
4591 if(!unitTarget->isAlive())
4592 return;
4594 // multiple weapon dmg effect workaround
4595 // execute only the last weapon damage
4596 // and handle all effects at once
4597 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
4599 switch(m_spellInfo->Effect[j])
4601 case SPELL_EFFECT_WEAPON_DAMAGE:
4602 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4603 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4604 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4605 if (j < int(eff_idx)) // we must calculate only at last weapon effect
4606 return;
4607 break;
4611 // some spell specific modifiers
4612 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4614 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4615 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4616 bool normalized = false;
4618 int32 spell_bonus = 0; // bonus specific for spell
4619 switch(m_spellInfo->SpellFamilyName)
4621 case SPELLFAMILY_WARRIOR:
4623 // Devastate bonus and sunder armor refresh
4624 if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4626 uint32 stack = 0;
4627 // Need refresh all Sunder Armor auras from this caster
4628 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4629 SpellEntry const *spellInfo;
4630 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4632 spellInfo = (*itr).second->GetSpellProto();
4633 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4634 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4635 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4637 (*itr).second->RefreshAura();
4638 stack = (*itr).second->GetStackAmount();
4639 break;
4642 if (stack)
4643 spell_bonus += stack * CalculateDamage(EFFECT_INDEX_2, unitTarget);
4644 if (!stack || stack < spellInfo->StackAmount)
4645 // Devastate causing Sunder Armor Effect
4646 // and no need to cast over max stack amount
4647 m_caster->CastSpell(unitTarget, 58567, true);
4649 break;
4651 case SPELLFAMILY_ROGUE:
4653 // Mutilate (for each hand)
4654 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4656 bool found = false;
4657 // fast check
4658 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4659 found = true;
4660 // full aura scan
4661 else
4663 Unit::AuraMap const& auras = unitTarget->GetAuras();
4664 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4666 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4668 found = true;
4669 break;
4674 if(found)
4675 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4677 // Fan of Knives
4678 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4680 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
4681 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4682 totalDamagePercentMod *= 1.5f; // 150% to daggers
4684 break;
4686 case SPELLFAMILY_PALADIN:
4688 // Judgement of Command - receive benefit from Spell Damage and Attack Power
4689 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000000000))
4691 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
4692 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
4693 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
4694 spell_bonus += int32(ap * 0.08f) + int32(holy * 13 / 100);
4696 break;
4698 case SPELLFAMILY_HUNTER:
4700 // Kill Shot
4701 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x80000000000000))
4703 // 0.4*RAP added to damage (that is 0.2 if we apply PercentMod (200%) to spell_bonus, too)
4704 spellBonusNeedWeaponDamagePercentMod = true;
4705 spell_bonus += int32( 0.2f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK) );
4707 break;
4709 case SPELLFAMILY_SHAMAN:
4711 // Skyshatter Harness item set bonus
4712 // Stormstrike
4713 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4715 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4716 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4718 // Stormstrike AP Buff
4719 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4721 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4722 break;
4726 break;
4728 case SPELLFAMILY_DEATHKNIGHT:
4730 // Blood Strike, Heart Strike, Obliterate
4731 // Blood-Caked Strike, Scourge Strike
4732 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
4733 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
4735 uint32 count = 0;
4736 Unit::AuraMap const& auras = unitTarget->GetAuras();
4737 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4739 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
4740 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
4741 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
4742 ++count;
4745 if (count)
4747 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4748 float bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? EFFECT_INDEX_0 : EFFECT_INDEX_2, unitTarget) / 100.0f;
4749 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4750 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
4751 m_spellInfo->SpellIconID == 1736)
4752 bonus /= 2.0f;
4754 totalDamagePercentMod *= 1.0f + bonus;
4757 // Heart Strike secondary target
4758 if (m_spellInfo->SpellIconID == 3145)
4759 if (m_targets.getUnitTarget() != unitTarget)
4760 weaponDamagePercentMod /= 2.0f;
4762 // Glyph of Blood Strike
4763 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000) &&
4764 m_caster->HasAura(59332) &&
4765 unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
4767 totalDamagePercentMod *= 1.2f; // 120% if snared
4769 // Glyph of Death Strike
4770 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010) &&
4771 m_caster->HasAura(59336))
4773 int32 rp = m_caster->GetPower(POWER_RUNIC_POWER) / 10;
4774 if(rp > 25)
4775 rp = 25;
4776 totalDamagePercentMod *= 1.0f + rp / 100.0f;
4778 // Glyph of Plague Strike
4779 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001) &&
4780 m_caster->HasAura(58657) )
4782 totalDamagePercentMod *= 1.2f;
4784 break;
4788 int32 fixed_bonus = 0;
4789 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
4791 switch(m_spellInfo->Effect[j])
4793 case SPELL_EFFECT_WEAPON_DAMAGE:
4794 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4795 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
4796 break;
4797 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4798 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
4799 normalized = true;
4800 break;
4801 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4802 weaponDamagePercentMod *= float(CalculateDamage(SpellEffectIndex(j), unitTarget)) / 100.0f;
4804 // applied only to prev.effects fixed damage
4805 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4806 break;
4807 default:
4808 break; // not weapon damage effect, just skip
4812 // apply weaponDamagePercentMod to spell bonus also
4813 if(spellBonusNeedWeaponDamagePercentMod)
4814 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4816 // non-weapon damage
4817 int32 bonus = spell_bonus + fixed_bonus;
4819 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4820 if(bonus)
4822 UnitMods unitMod;
4823 switch(m_attackType)
4825 default:
4826 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4827 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4828 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4831 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4832 bonus = int32(bonus*weapon_total_pct);
4835 // + weapon damage with applied weapon% dmg to base weapon damage in call
4836 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4838 // total damage
4839 bonus = int32(bonus*totalDamagePercentMod);
4841 // prevent negative damage
4842 m_damage+= uint32(bonus > 0 ? bonus : 0);
4844 // Hemorrhage
4845 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
4847 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4848 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4850 // Mangle (Cat): CP
4851 else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
4853 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4854 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4857 // take ammo
4858 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4860 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
4862 // wands don't have ammo
4863 if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
4864 return;
4866 if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
4868 if(pItem->GetMaxStackCount()==1)
4870 // decrease durability for non-stackable throw weapon
4871 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4873 else
4875 // decrease items amount for stackable throw weapon
4876 uint32 count = 1;
4877 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4880 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4881 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4885 void Spell::EffectThreat(SpellEffectIndex /*eff_idx*/)
4887 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4888 return;
4890 if(!unitTarget->CanHaveThreatList())
4891 return;
4893 unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
4896 void Spell::EffectHealMaxHealth(SpellEffectIndex /*eff_idx*/)
4898 if(!unitTarget)
4899 return;
4900 if(!unitTarget->isAlive())
4901 return;
4903 uint32 heal = m_caster->GetMaxHealth();
4905 m_healing += heal;
4908 void Spell::EffectInterruptCast(SpellEffectIndex /*eff_idx*/)
4910 if(!unitTarget)
4911 return;
4912 if(!unitTarget->isAlive())
4913 return;
4915 // TODO: not all spells that used this effect apply cooldown at school spells
4916 // also exist case: apply cooldown to interrupted cast only and to all spells
4917 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
4919 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
4921 SpellEntry const* curSpellInfo = spell->m_spellInfo;
4922 // check if we can interrupt spell
4923 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4925 unitTarget->ProhibitSpellSchool(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
4926 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
4932 void Spell::EffectSummonObjectWild(SpellEffectIndex eff_idx)
4934 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
4936 GameObject* pGameObj = new GameObject;
4938 WorldObject* target = focusObject;
4939 if( !target )
4940 target = m_caster;
4942 float x, y, z;
4943 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4945 x = m_targets.m_destX;
4946 y = m_targets.m_destY;
4947 z = m_targets.m_destZ;
4949 else
4950 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4952 Map *map = target->GetMap();
4954 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4955 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4957 delete pGameObj;
4958 return;
4961 int32 duration = GetSpellDuration(m_spellInfo);
4963 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4964 pGameObj->SetSpellId(m_spellInfo->Id);
4966 // Wild object not have owner and check clickable by players
4967 map->Add(pGameObj);
4969 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
4971 Player *pl = (Player*)m_caster;
4972 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4974 switch(pGameObj->GetMapId())
4976 case 489: //WS
4978 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4980 uint32 team = ALLIANCE;
4982 if(pl->GetTeam() == team)
4983 team = HORDE;
4985 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4987 break;
4989 case 566: //EY
4991 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4993 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4995 break;
5000 pGameObj->SummonLinkedTrapIfAny();
5003 void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
5005 // TODO: we must implement hunter pet summon at login there (spell 6962)
5007 switch(m_spellInfo->SpellFamilyName)
5009 case SPELLFAMILY_GENERIC:
5011 switch(m_spellInfo->Id)
5013 // Bending Shinbone
5014 case 8856:
5016 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
5017 return;
5019 uint32 spell_id = 0;
5020 switch(urand(1, 5))
5022 case 1: spell_id = 8854; break;
5023 default: spell_id = 8855; break;
5026 m_caster->CastSpell(m_caster,spell_id,true,NULL);
5027 return;
5029 // Piccolo of the Flaming Fire
5030 case 17512:
5032 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5033 return;
5034 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
5035 return;
5037 // Escape artist
5038 case 20589:
5040 if(!unitTarget)
5041 return;
5043 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5044 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5045 return;
5047 // Brittle Armor - need remove one 24575 Brittle Armor aura
5048 case 24590:
5049 unitTarget->RemoveSingleSpellAurasFromStack(24575);
5050 return;
5051 // PX-238 Winter Wondervolt TRAP
5052 case 26275:
5054 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
5056 // check presence
5057 for(int j = 0; j < 4; ++j)
5058 if(unitTarget->HasAura(spells[j], EFFECT_INDEX_0))
5059 return;
5061 // select spell
5062 uint32 iTmpSpellId = spells[urand(0,3)];
5064 // cast
5065 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
5066 return;
5068 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5069 case 26465:
5070 unitTarget->RemoveSingleSpellAurasFromStack(26464);
5071 return;
5072 // Orb teleport spells
5073 case 25140:
5074 case 25143:
5075 case 25650:
5076 case 25652:
5077 case 29128:
5078 case 29129:
5079 case 35376:
5080 case 35727:
5082 if(!unitTarget)
5083 return;
5085 uint32 spellid;
5086 switch(m_spellInfo->Id)
5088 case 25140: spellid = 32571; break;
5089 case 25143: spellid = 32572; break;
5090 case 25650: spellid = 30140; break;
5091 case 25652: spellid = 30141; break;
5092 case 29128: spellid = 32568; break;
5093 case 29129: spellid = 32569; break;
5094 case 35376: spellid = 25649; break;
5095 case 35727: spellid = 35730; break;
5096 default:
5097 return;
5100 unitTarget->CastSpell(unitTarget,spellid,false);
5101 return;
5103 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
5104 case 22539:
5105 case 22972:
5106 case 22975:
5107 case 22976:
5108 case 22977:
5109 case 22978:
5110 case 22979:
5111 case 22980:
5112 case 22981:
5113 case 22982:
5114 case 22983:
5115 case 22984:
5116 case 22985:
5118 if(!unitTarget || !unitTarget->isAlive())
5119 return;
5121 // Onyxia Scale Cloak
5122 if(unitTarget->GetDummyAura(22683))
5123 return;
5125 // Shadow Flame
5126 m_caster->CastSpell(unitTarget, 22682, true);
5127 return;
5129 // Summon Black Qiraji Battle Tank
5130 case 26656:
5132 if(!unitTarget)
5133 return;
5135 // Prevent stacking of mounts
5136 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5138 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5139 if (unitTarget->GetAreaId() == 3428)
5140 unitTarget->CastSpell(unitTarget, 25863, false);
5141 else
5142 unitTarget->CastSpell(unitTarget, 26655, false);
5143 return;
5145 // Mirren's Drinking Hat
5146 case 29830:
5148 uint32 item = 0;
5149 switch ( urand(1, 6) )
5151 case 1:
5152 case 2:
5153 case 3:
5154 item = 23584; break; // Loch Modan Lager
5155 case 4:
5156 case 5:
5157 item = 23585; break; // Stouthammer Lite
5158 case 6:
5159 item = 23586; break; // Aerie Peak Pale Ale
5161 if (item)
5162 DoCreateItem(eff_idx,item);
5163 break;
5165 // Improved Sprint
5166 case 30918:
5168 if(!unitTarget)
5169 return;
5170 // Removes snares and roots.
5171 unitTarget->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,30918,true);
5172 break;
5174 // Flame Crash
5175 case 41126:
5177 if(!unitTarget)
5178 return;
5180 unitTarget->CastSpell(unitTarget, 41131, true);
5181 break;
5183 // Force Cast - Portal Effect: Sunwell Isle
5184 case 44876:
5186 if(!unitTarget)
5187 return;
5189 unitTarget->CastSpell(unitTarget, 44870, true);
5190 break;
5192 // Goblin Weather Machine
5193 case 46203:
5195 if(!unitTarget)
5196 return;
5198 uint32 spellId = 0;
5199 switch(rand() % 4)
5201 case 0: spellId = 46740; break;
5202 case 1: spellId = 46739; break;
5203 case 2: spellId = 46738; break;
5204 case 3: spellId = 46736; break;
5206 unitTarget->CastSpell(unitTarget, spellId, true);
5207 break;
5209 //5,000 Gold
5210 case 46642:
5212 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5213 return;
5215 ((Player*)unitTarget)->ModifyMoney(50000000);
5217 break;
5219 // Surge Needle Teleporter
5220 case 47097:
5222 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5223 return;
5225 if (unitTarget->GetAreaId() == 4156)
5226 unitTarget->CastSpell(unitTarget, 47324, true);
5227 else if (unitTarget->GetAreaId() == 4157)
5228 unitTarget->CastSpell(unitTarget, 47325, true);
5230 break;
5232 // High Executor's Branding Iron
5233 case 48603:
5234 // Torture the Torturer: High Executor's Branding Iron Impact
5235 unitTarget->CastSpell(unitTarget, 48614, true);
5236 return;
5237 // Emblazon Runeblade
5238 case 51770:
5240 Unit* caster = GetAffectiveCaster();
5241 if(!caster)
5242 return;
5244 caster->CastSpell(caster, damage, false);
5245 break;
5247 // Death Gate
5248 case 52751:
5250 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5251 return;
5252 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5253 unitTarget->CastSpell(unitTarget, damage, false);
5254 break;
5256 // Winged Steed of the Ebon Blade
5257 case 54729:
5259 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5260 return;
5262 // Prevent stacking of mounts
5263 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5265 // Triggered spell id dependent of riding skill
5266 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5268 if (skillval >= 300)
5269 unitTarget->CastSpell(unitTarget, 54727, true);
5270 else
5271 unitTarget->CastSpell(unitTarget, 54726, true);
5273 return;
5275 // Demonic Empowerment (succubus Vanish effect)
5276 case 54436:
5278 if(!unitTarget)
5279 return;
5281 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5282 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5283 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
5284 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
5285 return;
5287 case 55693: // Remove Collapsing Cave Aura
5288 if(!unitTarget)
5289 return;
5290 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(eff_idx));
5291 break;
5292 case 58418: // Portal to Orgrimmar
5293 case 58420: // Portal to Stormwind
5295 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || eff_idx != EFFECT_INDEX_0)
5296 return;
5298 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
5299 uint32 questID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
5301 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5302 unitTarget->CastSpell(unitTarget, spellID, true);
5304 return;
5306 case 59317: // Teleporting
5307 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5308 return;
5310 // return from top
5311 if (((Player*)unitTarget)->GetAreaId() == 4637)
5312 unitTarget->CastSpell(unitTarget, 59316, true);
5313 // teleport atop
5314 else
5315 unitTarget->CastSpell(unitTarget, 59314, true);
5317 return;
5318 // random spell learn instead placeholder
5319 case 60893: // Northrend Alchemy Research
5320 case 61177: // Northrend Inscription Research
5321 case 61288: // Minor Inscription Research
5322 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5323 case 64323: // Book of Glyph Mastery
5325 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5326 return;
5328 // learn random explicit discovery recipe (if any)
5329 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5330 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5331 return;
5333 case 69377: //Fortitude
5335 if(!unitTarget)
5336 return;
5338 m_caster->CastSpell(unitTarget, 72590, true);
5339 return;
5341 case 69378: //Blessing of Forgotten Kings
5343 if(!unitTarget)
5344 return;
5346 m_caster->CastSpell(unitTarget, 72586, true);
5347 return;
5349 case 69381: //Gift of the Wild
5351 if(!unitTarget)
5352 return;
5354 m_caster->CastSpell(unitTarget, 72588, true);
5355 return;
5358 break;
5360 case SPELLFAMILY_WARLOCK:
5362 switch(m_spellInfo->Id)
5364 // Healthstone creating spells
5365 case 6201:
5366 case 6202:
5367 case 5699:
5368 case 11729:
5369 case 11730:
5370 case 27230:
5371 case 47871:
5372 case 47878:
5374 if(!unitTarget)
5375 return;
5376 uint32 itemtype;
5377 uint32 rank = 0;
5378 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5379 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5381 if((*i)->GetId() == 18692)
5383 rank = 1;
5384 break;
5386 else if((*i)->GetId() == 18693)
5388 rank = 2;
5389 break;
5393 static uint32 const itypes[8][3] = {
5394 { 5512, 19004, 19005}, // Minor Healthstone
5395 { 5511, 19006, 19007}, // Lesser Healthstone
5396 { 5509, 19008, 19009}, // Healthstone
5397 { 5510, 19010, 19011}, // Greater Healthstone
5398 { 9421, 19012, 19013}, // Major Healthstone
5399 {22103, 22104, 22105}, // Master Healthstone
5400 {36889, 36890, 36891}, // Demonic Healthstone
5401 {36892, 36893, 36894} // Fel Healthstone
5404 switch(m_spellInfo->Id)
5406 case 6201:
5407 itemtype=itypes[0][rank];break; // Minor Healthstone
5408 case 6202:
5409 itemtype=itypes[1][rank];break; // Lesser Healthstone
5410 case 5699:
5411 itemtype=itypes[2][rank];break; // Healthstone
5412 case 11729:
5413 itemtype=itypes[3][rank];break; // Greater Healthstone
5414 case 11730:
5415 itemtype=itypes[4][rank];break; // Major Healthstone
5416 case 27230:
5417 itemtype=itypes[5][rank];break; // Master Healthstone
5418 case 47871:
5419 itemtype=itypes[6][rank];break; // Demonic Healthstone
5420 case 47878:
5421 itemtype=itypes[7][rank];break; // Fel Healthstone
5422 default:
5423 return;
5425 DoCreateItem( eff_idx, itemtype );
5426 return;
5428 // Demonic Empowerment
5429 case 47193:
5431 if(!unitTarget)
5432 return;
5433 uint32 entry = unitTarget->GetEntry();
5434 uint32 spellID;
5435 switch(entry)
5437 case 416: spellID = 54444; break; //imp
5438 case 417: spellID = 54509; break; //fellhunter
5439 case 1860: spellID = 54443; break; //void
5440 case 1863: spellID = 54435; break; //succubus
5441 case 17252: spellID = 54508; break; //fellguard
5442 default:
5443 return;
5445 unitTarget->CastSpell(unitTarget,spellID,true);
5446 return;
5448 // Everlasting Affliction
5449 case 47422:
5451 // Need refresh caster corruption auras on target
5452 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5453 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5455 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5456 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5457 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5458 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5459 (*itr).second->RefreshAura();
5461 return;
5463 // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5464 case 63521:
5466 // Divine Plea, refresh on target (3 aura slots)
5467 if (Aura* aura = unitTarget->GetAura(54428, EFFECT_INDEX_0))
5468 aura->RefreshAura();
5469 return;
5472 break;
5474 case SPELLFAMILY_PRIEST:
5476 switch(m_spellInfo->Id)
5478 // Pain and Suffering
5479 case 47948:
5481 if (!unitTarget)
5482 return;
5483 // Refresh Shadow Word: Pain on target
5484 Unit::AuraMap& auras = unitTarget->GetAuras();
5485 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5487 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5488 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5489 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5490 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5492 (*itr).second->RefreshAura();
5493 return;
5496 return;
5498 default:
5499 break;
5501 break;
5503 case SPELLFAMILY_HUNTER:
5505 switch(m_spellInfo->Id)
5507 // Chimera Shot
5508 case 53209:
5510 if(!unitTarget)
5511 return;
5512 uint32 spellId = 0;
5513 int32 basePoint = 0;
5514 Unit* target = unitTarget;
5515 Unit::AuraMap& Auras = unitTarget->GetAuras();
5516 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5518 Aura *aura = (*i).second;
5519 if (aura->GetCasterGUID() != m_caster->GetGUID())
5520 continue;
5521 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5522 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5523 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5524 continue;
5525 // Refresh aura duration
5526 aura->RefreshAura();
5528 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5529 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5531 // m_amount already include RAP bonus
5532 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5533 spellId = 53353; // Chimera Shot - Serpent
5535 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5536 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5538 uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
5539 if (!target_max_mana)
5540 continue;
5542 // ignore non positive values (can be result apply spellmods to aura damage
5543 uint32 pdamage = aura->GetModifier()->m_amount > 0 ? aura->GetModifier()->m_amount : 0;
5545 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5546 uint32 maxmana = m_caster->GetMaxPower(POWER_MANA) * pdamage * 2 / 100;
5548 pdamage = target_max_mana * pdamage / 100;
5549 if (pdamage > maxmana)
5550 pdamage = maxmana;
5552 pdamage *= 4; // total aura damage
5553 basePoint = pdamage * 60 / 100;
5554 spellId = 53358; // Chimera Shot - Viper
5555 target = m_caster;
5557 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5558 if (familyFlag & UI64LIT(0x0000000000008000))
5559 spellId = 53359; // Chimera Shot - Scorpid
5560 // ?? nothing say in spell desc (possibly need addition check)
5561 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5562 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5564 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5567 if (spellId)
5568 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5569 return;
5571 case 53412: // Invigoration (pet triggered script, master targeted)
5573 if (!unitTarget)
5574 return;
5576 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5577 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5579 // Invigoration (master talent)
5580 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5582 if (roll_chance_i((*i)->GetModifier()->m_amount))
5584 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5585 break;
5589 return;
5591 // Master's Call
5592 case 53271:
5594 if (!unitTarget)
5595 return;
5597 // script effect have in value, but this outdated removed part
5598 unitTarget->CastSpell(unitTarget, 62305, true);
5599 return;
5601 default:
5602 break;
5604 break;
5606 case SPELLFAMILY_PALADIN:
5608 // Judgement (seal trigger)
5609 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5611 if(!unitTarget || !unitTarget->isAlive())
5612 return;
5613 uint32 spellId1 = 0;
5614 uint32 spellId2 = 0;
5616 // Judgement self add switch
5617 switch (m_spellInfo->Id)
5619 case 53407: spellId1 = 20184; break; // Judgement of Justice
5620 case 20271: // Judgement of Light
5621 case 57774: spellId1 = 20185; break; // Judgement of Light
5622 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5623 default:
5624 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
5625 return;
5627 // offensive seals have aura dummy in 2 effect
5628 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5629 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5631 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
5632 if ((*itr)->GetEffIndex() != EFFECT_INDEX_2 || !IsSealSpell((*itr)->GetSpellProto()))
5633 continue;
5634 spellId2 = (*itr)->GetModifier()->m_amount;
5635 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5636 if (!judge)
5637 continue;
5638 break;
5640 // if there were no offensive seals than there is seal with proc trigger aura
5641 if (!spellId2)
5643 Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5644 for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
5646 if ((*itr)->GetEffIndex() != EFFECT_INDEX_0 || !IsSealSpell((*itr)->GetSpellProto()))
5647 continue;
5648 spellId2 = 54158;
5649 break;
5652 if (spellId1)
5653 m_caster->CastSpell(unitTarget, spellId1, true);
5654 if (spellId2)
5655 m_caster->CastSpell(unitTarget, spellId2, true);
5656 return;
5659 case SPELLFAMILY_POTION:
5661 switch(m_spellInfo->Id)
5663 // Dreaming Glory
5664 case 28698:
5666 if(!unitTarget)
5667 return;
5668 unitTarget->CastSpell(unitTarget, 28694, true);
5669 break;
5671 // Netherbloom
5672 case 28702:
5674 if(!unitTarget)
5675 return;
5676 // 25% chance of casting a random buff
5677 if(roll_chance_i(75))
5678 return;
5680 // triggered spells are 28703 to 28707
5681 // Note: some sources say, that there was the possibility of
5682 // receiving a debuff. However, this seems to be removed by a patch.
5683 const uint32 spellid = 28703;
5685 // don't overwrite an existing aura
5686 for(uint8 i = 0; i < 5; ++i)
5687 if (unitTarget->HasAura(spellid + i, EFFECT_INDEX_0))
5688 return;
5689 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5690 break;
5693 // Nightmare Vine
5694 case 28720:
5696 if(!unitTarget)
5697 return;
5698 // 25% chance of casting Nightmare Pollen
5699 if(roll_chance_i(75))
5700 return;
5701 unitTarget->CastSpell(unitTarget, 28721, true);
5702 break;
5705 break;
5707 case SPELLFAMILY_DEATHKNIGHT:
5709 switch(m_spellInfo->Id)
5711 // Pestilence
5712 case 50842:
5714 if(!unitTarget)
5715 return;
5717 Unit* mainTarget = m_targets.getUnitTarget();
5718 if(!mainTarget)
5719 return;
5721 // do only refresh diseases on main target if caster has Glyph of Disease
5722 if(mainTarget == unitTarget && !m_caster->HasAura(63334))
5723 return;
5725 // Blood Plague
5726 if(mainTarget->HasAura(55078))
5727 m_caster->CastSpell(unitTarget, 55078, true);
5729 // Frost Fever
5730 if(mainTarget->HasAura(55095))
5731 m_caster->CastSpell(unitTarget, 55095, true);
5733 break;
5736 break;
5740 // normal DB scripted effect
5741 if(!unitTarget)
5742 return;
5744 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5745 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5748 void Spell::EffectSanctuary(SpellEffectIndex /*eff_idx*/)
5750 if(!unitTarget)
5751 return;
5752 //unitTarget->CombatStop();
5754 unitTarget->CombatStop();
5755 unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
5756 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5757 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5759 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5763 void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/)
5765 if(!unitTarget)
5766 return;
5768 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5769 return;
5771 if(damage <= 0)
5772 return;
5774 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5777 void Spell::EffectDuel(SpellEffectIndex eff_idx)
5779 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5780 return;
5782 Player *caster = (Player*)m_caster;
5783 Player *target = (Player*)unitTarget;
5785 // caster or target already have requested duel
5786 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5787 return;
5789 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5790 // Don't have to check the target's map since you cannot challenge someone across maps
5791 uint32 mapid = caster->GetMapId();
5792 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5794 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5795 return;
5798 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5799 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5801 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5802 return;
5805 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5806 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5808 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5809 return;
5812 //CREATE DUEL FLAG OBJECT
5813 GameObject* pGameObj = new GameObject;
5815 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
5817 Map *map = m_caster->GetMap();
5818 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5819 map, m_caster->GetPhaseMask(),
5820 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5821 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5822 m_caster->GetPositionZ(),
5823 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5825 delete pGameObj;
5826 return;
5829 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5830 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5831 int32 duration = GetSpellDuration(m_spellInfo);
5832 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5833 pGameObj->SetSpellId(m_spellInfo->Id);
5835 m_caster->AddGameObject(pGameObj);
5836 map->Add(pGameObj);
5837 //END
5839 // Send request
5840 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
5841 data << uint64(pGameObj->GetGUID());
5842 data << uint64(caster->GetGUID());
5843 caster->GetSession()->SendPacket(&data);
5844 target->GetSession()->SendPacket(&data);
5846 // create duel-info
5847 DuelInfo *duel = new DuelInfo;
5848 duel->initiator = caster;
5849 duel->opponent = target;
5850 duel->startTime = 0;
5851 duel->startTimer = 0;
5852 caster->duel = duel;
5854 DuelInfo *duel2 = new DuelInfo;
5855 duel2->initiator = caster;
5856 duel2->opponent = caster;
5857 duel2->startTime = 0;
5858 duel2->startTimer = 0;
5859 target->duel = duel2;
5861 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5862 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5865 void Spell::EffectStuck(SpellEffectIndex /*eff_idx*/)
5867 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5868 return;
5870 if(!sWorld.getConfig(CONFIG_BOOL_CAST_UNSTUCK))
5871 return;
5873 Player* pTarget = (Player*)unitTarget;
5875 sLog.outDebug("Spell Effect: Stuck");
5876 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());
5878 if(pTarget->isInFlight())
5879 return;
5881 // homebind location is loaded always
5882 pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
5884 // Stuck spell trigger Hearthstone cooldown
5885 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5886 if(!spellInfo)
5887 return;
5888 Spell spell(pTarget, spellInfo, true, 0);
5889 spell.SendSpellCooldown();
5892 void Spell::EffectSummonPlayer(SpellEffectIndex /*eff_idx*/)
5894 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5895 return;
5897 // Evil Twin (ignore player summon, but hide this for summoner)
5898 if(unitTarget->GetDummyAura(23445))
5899 return;
5901 float x, y, z;
5902 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
5904 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5906 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5907 data << uint64(m_caster->GetGUID()); // summoner guid
5908 data << uint32(m_caster->GetZoneId()); // summoner zone
5909 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5910 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5913 static ScriptInfo generateActivateCommand()
5915 ScriptInfo si;
5916 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5917 return si;
5920 void Spell::EffectActivateObject(SpellEffectIndex eff_idx)
5922 if(!gameObjTarget)
5923 return;
5925 static ScriptInfo activateCommand = generateActivateCommand();
5927 int32 delay_secs = m_spellInfo->CalculateSimpleValue(eff_idx);
5929 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5932 void Spell::EffectApplyGlyph(SpellEffectIndex eff_idx)
5934 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5935 return;
5937 Player *player = (Player*)m_caster;
5939 // apply new one
5940 if(uint32 glyph = m_spellInfo->EffectMiscValue[eff_idx])
5942 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5944 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5946 if(gp->TypeFlags != gs->TypeFlags)
5948 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5949 return; // glyph slot mismatch
5953 // remove old glyph
5954 player->ApplyGlyph(m_glyphIndex, false);
5955 player->SetGlyph(m_glyphIndex, glyph);
5956 player->ApplyGlyph(m_glyphIndex, true);
5957 player->SendTalentsInfoData(false);
5962 void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot)
5964 slot = slot ? (slot - 1): 255;
5966 if(slot < MAX_TOTEM)
5968 uint64 guid = m_caster->m_TotemSlot[slot];
5969 if(guid != 0)
5971 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5972 if(OldTotem && OldTotem->isTotem())
5973 ((Totem*)OldTotem)->UnSummon();
5977 uint32 team = 0;
5978 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5979 team = ((Player*)m_caster)->GetTeam();
5981 Totem* pTotem = new Totem;
5983 if(!pTotem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5984 m_spellInfo->EffectMiscValue[eff_idx], team ))
5986 delete pTotem;
5987 return;
5990 float angle = slot < MAX_TOTEM ? M_PI_F/MAX_TOTEM - (slot*2*M_PI_F/MAX_TOTEM) : 0;
5992 float x, y, z;
5993 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
5995 // totem must be at same Z in case swimming caster and etc.
5996 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5997 z = m_caster->GetPositionZ();
5999 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
6001 if(slot < MAX_TOTEM)
6002 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
6004 pTotem->SetOwner(m_caster->GetGUID());
6005 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
6007 int32 duration=GetSpellDuration(m_spellInfo);
6008 if(Player* modOwner = m_caster->GetSpellModOwner())
6009 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
6010 pTotem->SetDuration(duration);
6012 if (damage) // if not spell info, DB values used
6014 pTotem->SetMaxHealth(damage);
6015 pTotem->SetHealth(damage);
6018 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6020 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6021 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
6023 if(m_caster->IsPvP())
6024 pTotem->SetPvP(true);
6026 if(m_caster->IsFFAPvP())
6027 pTotem->SetFFAPvP(true);
6029 pTotem->Summon(m_caster);
6031 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
6033 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
6034 data << uint8(slot);
6035 data << uint64(pTotem->GetGUID());
6036 data << uint32(duration);
6037 data << uint32(m_spellInfo->Id);
6038 ((Player*)m_caster)->SendDirectMessage(&data);
6042 void Spell::EffectEnchantHeldItem(SpellEffectIndex eff_idx)
6044 // this is only item spell effect applied to main-hand weapon of target player (players in area)
6045 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6046 return;
6048 Player* item_owner = (Player*)unitTarget;
6049 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
6051 if(!item )
6052 return;
6054 // must be equipped
6055 if(!item ->IsEquipped())
6056 return;
6058 if (m_spellInfo->EffectMiscValue[eff_idx])
6060 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
6061 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
6062 if(!duration)
6063 duration = m_currentBasePoints[eff_idx]+1; //Base points after ..
6064 if(!duration)
6065 duration = 10; //10 seconds for enchants which don't have listed duration
6067 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6068 if(!pEnchant)
6069 return;
6071 // Always go to temp enchantment slot
6072 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
6074 // Enchantment will not be applied if a different one already exists
6075 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
6076 return;
6078 // Apply the temporary enchantment
6079 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
6080 item_owner->ApplyEnchantment(item, slot, true);
6084 void Spell::EffectDisEnchant(SpellEffectIndex /*eff_idx*/)
6086 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6087 return;
6089 Player* p_caster = (Player*)m_caster;
6090 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
6091 return;
6093 p_caster->UpdateCraftSkill(m_spellInfo->Id);
6095 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
6097 // item will be removed at disenchanting end
6100 void Spell::EffectInebriate(SpellEffectIndex /*eff_idx*/)
6102 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6103 return;
6105 Player *player = (Player*)unitTarget;
6106 uint16 currentDrunk = player->GetDrunkValue();
6107 uint16 drunkMod = damage * 256;
6108 if (currentDrunk + drunkMod > 0xFFFF)
6109 currentDrunk = 0xFFFF;
6110 else
6111 currentDrunk += drunkMod;
6112 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
6115 void Spell::EffectFeedPet(SpellEffectIndex eff_idx)
6117 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6118 return;
6120 Player *_player = (Player*)m_caster;
6122 Item* foodItem = m_targets.getItemTarget();
6123 if(!foodItem)
6124 return;
6126 Pet *pet = _player->GetPet();
6127 if(!pet)
6128 return;
6130 if(!pet->isAlive())
6131 return;
6133 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
6134 if(benefit <= 0)
6135 return;
6137 uint32 count = 1;
6138 _player->DestroyItemCount(foodItem,count,true);
6139 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6141 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[eff_idx], &benefit, NULL, NULL, true);
6144 void Spell::EffectDismissPet(SpellEffectIndex /*eff_idx*/)
6146 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6147 return;
6149 Pet* pet = m_caster->GetPet();
6151 // not let dismiss dead pet
6152 if(!pet||!pet->isAlive())
6153 return;
6155 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
6158 void Spell::EffectSummonObject(SpellEffectIndex eff_idx)
6160 uint32 go_id = m_spellInfo->EffectMiscValue[eff_idx];
6162 uint8 slot = 0;
6163 switch(m_spellInfo->Effect[eff_idx])
6165 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
6166 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
6167 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
6168 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
6169 default: return;
6172 if(uint64 guid = m_caster->m_ObjectSlot[slot])
6174 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
6175 obj->SetLootState(GO_JUST_DEACTIVATED);
6176 m_caster->m_ObjectSlot[slot] = 0;
6179 GameObject* pGameObj = new GameObject;
6181 float x, y, z;
6182 // If dest location if present
6183 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6185 x = m_targets.m_destX;
6186 y = m_targets.m_destY;
6187 z = m_targets.m_destZ;
6189 // Summon in random point all other units if location present
6190 else
6191 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
6193 Map *map = m_caster->GetMap();
6194 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
6195 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6197 delete pGameObj;
6198 return;
6201 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
6202 int32 duration = GetSpellDuration(m_spellInfo);
6203 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6204 pGameObj->SetSpellId(m_spellInfo->Id);
6205 m_caster->AddGameObject(pGameObj);
6207 map->Add(pGameObj);
6209 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
6211 pGameObj->SummonLinkedTrapIfAny();
6214 void Spell::EffectResurrect(SpellEffectIndex /*eff_idx*/)
6216 if(!unitTarget)
6217 return;
6218 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6219 return;
6221 if(unitTarget->isAlive())
6222 return;
6223 if(!unitTarget->IsInWorld())
6224 return;
6226 switch (m_spellInfo->Id)
6228 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6229 case 8342:
6230 if (roll_chance_i(67))
6232 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
6233 return;
6235 break;
6236 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6237 case 22999:
6238 if (roll_chance_i(50))
6240 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
6241 return;
6243 break;
6244 default:
6245 break;
6248 Player* pTarget = ((Player*)unitTarget);
6250 if(pTarget->isRessurectRequested()) // already have one active request
6251 return;
6253 uint32 health = pTarget->GetMaxHealth() * damage / 100;
6254 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
6256 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
6257 SendResurrectRequest(pTarget);
6260 void Spell::EffectAddExtraAttacks(SpellEffectIndex /*eff_idx*/)
6262 if(!unitTarget || !unitTarget->isAlive())
6263 return;
6265 if( unitTarget->m_extraAttacks )
6266 return;
6268 unitTarget->m_extraAttacks = damage;
6271 void Spell::EffectParry(SpellEffectIndex /*eff_idx*/)
6273 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6274 ((Player*)unitTarget)->SetCanParry(true);
6277 void Spell::EffectBlock(SpellEffectIndex /*eff_idx*/)
6279 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6280 ((Player*)unitTarget)->SetCanBlock(true);
6283 void Spell::EffectLeapForward(SpellEffectIndex eff_idx)
6285 if(unitTarget->isInFlight())
6286 return;
6288 if( m_spellInfo->rangeIndex == 1) //self range
6290 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
6292 // before caster
6293 float fx, fy, fz;
6294 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6295 float ox, oy, oz;
6296 unitTarget->GetPosition(ox, oy, oz);
6298 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6299 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5f, fx,fy,oz+0.5f,fx2,fy2,fz2, -0.5f))
6301 fx = fx2;
6302 fy = fy2;
6303 fz = fz2;
6304 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6307 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6311 void Spell::EffectLeapBack(SpellEffectIndex eff_idx)
6313 if(unitTarget->isInFlight())
6314 return;
6316 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6319 void Spell::EffectReputation(SpellEffectIndex eff_idx)
6321 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6322 return;
6324 Player *_player = (Player*)unitTarget;
6326 int32 rep_change = m_currentBasePoints[eff_idx]+1; // field store reputation change -1
6328 uint32 faction_id = m_spellInfo->EffectMiscValue[eff_idx];
6330 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6332 if(!factionEntry)
6333 return;
6335 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6338 void Spell::EffectQuestComplete(SpellEffectIndex eff_idx)
6340 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6341 return;
6343 Player *_player = (Player*)m_caster;
6345 uint32 quest_id = m_spellInfo->EffectMiscValue[eff_idx];
6346 _player->AreaExploredOrEventHappens(quest_id);
6349 void Spell::EffectSelfResurrect(SpellEffectIndex eff_idx)
6351 if(!unitTarget || unitTarget->isAlive())
6352 return;
6353 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6354 return;
6355 if(!unitTarget->IsInWorld())
6356 return;
6358 uint32 health = 0;
6359 uint32 mana = 0;
6361 // flat case
6362 if(damage < 0)
6364 health = uint32(-damage);
6365 mana = m_spellInfo->EffectMiscValue[eff_idx];
6367 // percent case
6368 else
6370 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6371 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6372 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6375 Player *plr = ((Player*)unitTarget);
6376 plr->ResurrectPlayer(0.0f);
6378 plr->SetHealth( health );
6379 plr->SetPower(POWER_MANA, mana );
6380 plr->SetPower(POWER_RAGE, 0 );
6381 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6383 plr->SpawnCorpseBones();
6386 void Spell::EffectSkinning(SpellEffectIndex /*eff_idx*/)
6388 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6389 return;
6390 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6391 return;
6393 Creature* creature = (Creature*) unitTarget;
6394 int32 targetLevel = creature->getLevel();
6396 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6398 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6399 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6401 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6403 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6405 // Double chances for elites
6406 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6409 void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/)
6411 if (!unitTarget)
6412 return;
6414 //TODO: research more ContactPoint/attack distance.
6415 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6416 float x, y, z;
6417 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6419 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6420 ((Creature *)unitTarget)->StopMoving();
6422 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6423 m_caster->MonsterMove(x, y, z, 1);
6425 // not all charge effects used in negative spells
6426 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6427 m_caster->Attack(unitTarget, true);
6430 void Spell::EffectCharge2(SpellEffectIndex /*eff_idx*/)
6432 float x, y, z;
6433 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6435 x = m_targets.m_destX;
6436 y = m_targets.m_destY;
6437 z = m_targets.m_destZ;
6439 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6440 ((Creature *)unitTarget)->StopMoving();
6442 else if (unitTarget && unitTarget != m_caster)
6443 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6444 else
6445 return;
6447 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6448 m_caster->MonsterMove(x, y, z, 1);
6450 // not all charge effects used in negative spells
6451 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6452 m_caster->Attack(unitTarget, true);
6455 void Spell::DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction)
6457 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6458 return;
6459 Player* player = (Player*)m_caster;
6461 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
6462 if(!pet_entry)
6463 return;
6465 Pet* old_critter = player->GetMiniPet();
6467 // for same pet just despawn
6468 if(old_critter && old_critter->GetEntry() == pet_entry)
6470 player->RemoveMiniPet();
6471 return;
6474 // despawn old pet before summon new
6475 if(old_critter)
6476 player->RemoveMiniPet();
6478 // summon new pet
6479 Pet* critter = new Pet(MINI_PET);
6481 Map *map = m_caster->GetMap();
6482 uint32 pet_number = sObjectMgr.GeneratePetNumber();
6483 if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6484 pet_entry, pet_number))
6486 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6487 delete critter;
6488 return;
6491 float x, y, z;
6492 // If dest location if present
6493 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6495 x = m_targets.m_destX;
6496 y = m_targets.m_destY;
6497 z = m_targets.m_destZ;
6499 // Summon if dest location not present near caster
6500 else
6501 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6503 critter->Relocate(x, y, z, m_caster->GetOrientation());
6505 if(!critter->IsPositionValid())
6507 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6508 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6509 delete critter;
6510 return;
6513 critter->SetOwnerGUID(m_caster->GetGUID());
6514 critter->SetCreatorGUID(m_caster->GetGUID());
6516 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6517 critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
6518 critter->AIM_Initialize();
6519 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6520 //critter->InitLevelupSpellsForLevel(); // none?
6521 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6522 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6523 // some mini-pets have quests
6525 // set timer for unsummon
6526 int32 duration = GetSpellDuration(m_spellInfo);
6527 if(duration > 0)
6528 critter->SetDuration(duration);
6530 std::string name = player->GetName();
6531 name.append(petTypeSuffix[critter->getPetType()]);
6532 critter->SetName( name );
6533 player->SetMiniPet(critter);
6535 map->Add((Creature*)critter);
6538 void Spell::EffectKnockBack(SpellEffectIndex eff_idx)
6540 if(!unitTarget)
6541 return;
6543 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6546 void Spell::EffectSendTaxi(SpellEffectIndex eff_idx)
6548 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6549 return;
6551 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[eff_idx],m_spellInfo->Id);
6554 void Spell::EffectPlayerPull(SpellEffectIndex eff_idx)
6556 if(!unitTarget)
6557 return;
6559 float dist = unitTarget->GetDistance2d(m_caster);
6560 if (damage && dist > damage)
6561 dist = float(damage);
6563 unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[eff_idx])/10);
6566 void Spell::EffectDispelMechanic(SpellEffectIndex eff_idx)
6568 if(!unitTarget)
6569 return;
6571 uint32 mechanic = m_spellInfo->EffectMiscValue[eff_idx];
6573 Unit::AuraMap& Auras = unitTarget->GetAuras();
6574 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6576 next = iter;
6577 ++next;
6578 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6579 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6581 unitTarget->RemoveAurasDueToSpell(spell->Id);
6582 if(Auras.empty())
6583 break;
6584 else
6585 next = Auras.begin();
6588 return;
6591 void Spell::EffectSummonDeadPet(SpellEffectIndex /*eff_idx*/)
6593 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6594 return;
6595 Player *_player = (Player*)m_caster;
6596 Pet *pet = _player->GetPet();
6597 if(!pet)
6598 return;
6599 if(pet->isAlive())
6600 return;
6601 if(damage < 0)
6602 return;
6603 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6604 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6605 pet->setDeathState( ALIVE );
6606 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6607 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6609 pet->AIM_Initialize();
6611 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6612 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6615 void Spell::EffectSummonAllTotems(SpellEffectIndex eff_idx)
6617 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6618 return;
6620 int32 start_button = ACTION_BUTTON_SHAMAN_TOTEMS_BAR + m_spellInfo->EffectMiscValue[eff_idx];
6621 int32 amount_buttons = m_spellInfo->EffectMiscValueB[eff_idx];
6623 for(int32 slot = 0; slot < amount_buttons; ++slot)
6624 if (ActionButton const* actionButton = ((Player*)m_caster)->GetActionButton(start_button+slot))
6625 if (actionButton->GetType()==ACTION_BUTTON_SPELL)
6626 if (uint32 spell_id = actionButton->GetAction())
6627 m_caster->CastSpell(unitTarget,spell_id,true);
6630 void Spell::EffectDestroyAllTotems(SpellEffectIndex /*eff_idx*/)
6632 int32 mana = 0;
6633 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6635 if(!m_caster->m_TotemSlot[slot])
6636 continue;
6638 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6639 if(totem && totem->isTotem())
6641 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6642 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6643 if(spellInfo)
6645 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6646 mana += manacost * damage / 100;
6648 ((Totem*)totem)->UnSummon();
6652 if (mana)
6653 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
6656 void Spell::EffectDurabilityDamage(SpellEffectIndex eff_idx)
6658 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6659 return;
6661 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
6663 // FIXME: some spells effects have value -1/-2
6664 // Possibly its mean -1 all player equipped items and -2 all items
6665 if(slot < 0)
6667 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
6668 return;
6671 // invalid slot value
6672 if(slot >= INVENTORY_SLOT_BAG_END)
6673 return;
6675 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6676 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
6679 void Spell::EffectDurabilityDamagePCT(SpellEffectIndex eff_idx)
6681 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6682 return;
6684 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
6686 // FIXME: some spells effects have value -1/-2
6687 // Possibly its mean -1 all player equipped items and -2 all items
6688 if(slot < 0)
6690 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
6691 return;
6694 // invalid slot value
6695 if(slot >= INVENTORY_SLOT_BAG_END)
6696 return;
6698 if(damage <= 0)
6699 return;
6701 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6702 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
6705 void Spell::EffectModifyThreatPercent(SpellEffectIndex /*eff_idx*/)
6707 if(!unitTarget)
6708 return;
6710 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6713 void Spell::EffectTransmitted(SpellEffectIndex eff_idx)
6715 uint32 name_id = m_spellInfo->EffectMiscValue[eff_idx];
6717 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
6719 if (!goinfo)
6721 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6722 return;
6725 float fx, fy, fz;
6727 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6729 fx = m_targets.m_destX;
6730 fy = m_targets.m_destY;
6731 fz = m_targets.m_destZ;
6733 //FIXME: this can be better check for most objects but still hack
6734 else if(m_spellInfo->EffectRadiusIndex[eff_idx] && m_spellInfo->speed==0)
6736 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
6737 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6739 else
6741 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6742 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6743 float dis = rand_norm_f() * (max_dis - min_dis) + min_dis;
6745 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6748 Map *cMap = m_caster->GetMap();
6750 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6752 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6753 { // but this is not proper, we really need to ignore not materialized objects
6754 SendCastResult(SPELL_FAILED_NOT_HERE);
6755 SendChannelUpdate(0);
6756 return;
6759 // replace by water level in this case
6760 fz = cMap->GetWaterLevel(fx, fy);
6762 // if gameobject is summoning object, it should be spawned right on caster's position
6763 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6765 m_caster->GetPosition(fx, fy, fz);
6768 GameObject* pGameObj = new GameObject;
6770 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6771 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6773 delete pGameObj;
6774 return;
6777 int32 duration = GetSpellDuration(m_spellInfo);
6779 switch(goinfo->type)
6781 case GAMEOBJECT_TYPE_FISHINGNODE:
6783 m_caster->SetChannelObjectGUID(pGameObj->GetGUID());
6784 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6786 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6787 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6788 int32 lastSec = 0;
6789 switch(urand(0, 3))
6791 case 0: lastSec = 3; break;
6792 case 1: lastSec = 7; break;
6793 case 2: lastSec = 13; break;
6794 case 3: lastSec = 17; break;
6797 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6798 break;
6800 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6802 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6804 pGameObj->AddUniqueUse((Player*)m_caster);
6805 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6807 break;
6809 case GAMEOBJECT_TYPE_FISHINGHOLE:
6810 case GAMEOBJECT_TYPE_CHEST:
6811 default:
6812 break;
6815 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6817 pGameObj->SetOwnerGUID(m_caster->GetGUID());
6819 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6820 pGameObj->SetSpellId(m_spellInfo->Id);
6822 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6823 //m_caster->AddGameObject(pGameObj);
6824 //m_ObjToDel.push_back(pGameObj);
6826 cMap->Add(pGameObj);
6828 pGameObj->SummonLinkedTrapIfAny();
6831 void Spell::EffectProspecting(SpellEffectIndex /*eff_idx*/)
6833 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6834 return;
6836 Player* p_caster = (Player*)m_caster;
6837 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6838 return;
6840 if(itemTarget->GetCount() < 5)
6841 return;
6843 if( sWorld.getConfig(CONFIG_BOOL_SKILL_PROSPECTING))
6845 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6846 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6847 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6850 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6853 void Spell::EffectMilling(SpellEffectIndex /*eff_idx*/)
6855 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6856 return;
6858 Player* p_caster = (Player*)m_caster;
6859 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6860 return;
6862 if(itemTarget->GetCount() < 5)
6863 return;
6865 if( sWorld.getConfig(CONFIG_BOOL_SKILL_MILLING))
6867 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6868 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6869 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6872 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6875 void Spell::EffectSkill(SpellEffectIndex /*eff_idx*/)
6877 sLog.outDebug("WORLD: SkillEFFECT");
6880 void Spell::EffectSpiritHeal(SpellEffectIndex /*eff_idx*/)
6882 // TODO player can't see the heal-animation - he should respawn some ticks later
6883 if (!unitTarget || unitTarget->isAlive())
6884 return;
6885 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6886 return;
6887 if (!unitTarget->IsInWorld())
6888 return;
6889 if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584))
6890 return;
6892 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6893 ((Player*)unitTarget)->SpawnCorpseBones();
6896 // remove insignia spell effect
6897 void Spell::EffectSkinPlayerCorpse(SpellEffectIndex /*eff_idx*/)
6899 sLog.outDebug("Effect: SkinPlayerCorpse");
6900 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6901 return;
6903 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6906 void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx)
6908 sLog.outDebug("Effect: StealBeneficialBuff");
6910 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6911 return;
6913 std::vector <Aura *> steal_list;
6914 // Create dispel mask by dispel type
6915 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[eff_idx]) );
6916 Unit::AuraMap const& auras = unitTarget->GetAuras();
6917 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6919 Aura *aur = (*itr).second;
6920 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6922 // Need check for passive? this
6923 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6924 steal_list.push_back(aur);
6927 // Ok if exist some buffs for dispel try dispel it
6928 if (!steal_list.empty())
6930 std::list < std::pair<uint32,uint64> > success_list;
6931 int32 list_size = steal_list.size();
6932 // Dispell N = damage buffs (or while exist buffs for dispel)
6933 for (int32 count=0; count < damage && list_size > 0; ++count)
6935 // Random select buff for dispel
6936 Aura *aur = steal_list[urand(0, list_size-1)];
6937 // Not use chance for steal
6938 // TODO possible need do it
6939 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6941 // Remove buff from list for prevent doubles
6942 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6944 Aura *stealed = *j;
6945 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6947 j = steal_list.erase(j);
6948 --list_size;
6950 else
6951 ++j;
6954 // Really try steal and send log
6955 if (!success_list.empty())
6957 int32 count = success_list.size();
6958 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6959 data.append(unitTarget->GetPackGUID()); // Victim GUID
6960 data.append(m_caster->GetPackGUID()); // Caster GUID
6961 data << uint32(m_spellInfo->Id); // Dispell spell id
6962 data << uint8(0); // not used
6963 data << uint32(count); // count
6964 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6966 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6967 data << uint32(spellInfo->Id); // Spell Id
6968 data << uint8(0); // 0 - steals !=0 transfers
6969 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6971 m_caster->SendMessageToSet(&data, true);
6976 void Spell::EffectKillCreditPersonal(SpellEffectIndex eff_idx)
6978 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6979 return;
6981 ((Player*)unitTarget)->KilledMonsterCredit(m_spellInfo->EffectMiscValue[eff_idx], 0);
6984 void Spell::EffectKillCredit(SpellEffectIndex eff_idx)
6986 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6987 return;
6989 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[eff_idx], unitTarget);
6992 void Spell::EffectQuestFail(SpellEffectIndex eff_idx)
6994 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6995 return;
6997 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[eff_idx]);
7000 void Spell::EffectActivateRune(SpellEffectIndex eff_idx)
7002 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7003 return;
7005 Player *plr = (Player*)m_caster;
7007 if(plr->getClass() != CLASS_DEATH_KNIGHT)
7008 return;
7010 for(uint32 j = 0; j < MAX_RUNES; ++j)
7012 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
7014 plr->SetRuneCooldown(j, 0);
7019 void Spell::EffectTitanGrip(SpellEffectIndex /*eff_idx*/)
7021 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
7022 ((Player*)unitTarget)->SetCanTitanGrip(true);
7025 void Spell::EffectRenamePet(SpellEffectIndex /*eff_idx*/)
7027 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
7028 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
7029 return;
7031 unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
7034 void Spell::EffectPlayMusic(SpellEffectIndex eff_idx)
7036 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7037 return;
7039 uint32 soundid = m_spellInfo->EffectMiscValue[eff_idx];
7041 if (!sSoundEntriesStore.LookupEntry(soundid))
7043 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
7044 return;
7047 WorldPacket data(SMSG_PLAY_MUSIC, 4);
7048 data << uint32(soundid);
7049 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
7052 void Spell::EffectSpecCount(SpellEffectIndex /*eff_idx*/)
7054 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7055 return;
7057 ((Player*)unitTarget)->UpdateSpecCount(damage);
7060 void Spell::EffectActivateSpec(SpellEffectIndex /*eff_idx*/)
7062 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7063 return;
7065 uint32 spec = damage-1;
7067 ((Player*)unitTarget)->ActivateSpec(spec);