[9024] Fixed RAP bonus percent for spell 56641 and ranks.
[getmangos.git] / src / game / SpellEffects.cpp
blobe61ba6462ca16cff819c5cd9c5a7d20e93099f4b
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::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::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectCharge2, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL, //160 SPELL_EFFECT_160 unused
221 &Spell::EffectNULL, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectNULL, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(uint32 /*i*/)
227 sLog.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(uint32 /*i*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(uint32 i)
237 if(!unitTarget || unitTarget->isAlive())
238 return;
240 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
241 return;
243 if(!unitTarget->IsInWorld())
244 return;
246 Player* pTarget = ((Player*)unitTarget);
248 if(pTarget->isRessurectRequested()) // already have one active request
249 return;
251 uint32 health = damage;
252 uint32 mana = m_spellInfo->EffectMiscValue[i];
253 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
254 SendResurrectRequest(pTarget);
257 void Spell::EffectInstaKill(uint32 /*i*/)
259 if( !unitTarget || !unitTarget->isAlive() )
260 return;
262 // Demonic Sacrifice
263 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
265 uint32 entry = unitTarget->GetEntry();
266 uint32 spellID;
267 switch(entry)
269 case 416: spellID=18789; break; //imp
270 case 417: spellID=18792; break; //fellhunter
271 case 1860: spellID=18790; break; //void
272 case 1863: spellID=18791; break; //succubus
273 case 17252: spellID=35701; break; //fellguard
274 default:
275 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
276 return;
279 m_caster->CastSpell(m_caster, spellID, true);
282 if(m_caster == unitTarget) // prevent interrupt message
283 finish();
285 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
288 void Spell::EffectEnvirinmentalDMG(uint32 i)
290 uint32 absorb = 0;
291 uint32 resist = 0;
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage = m_spellInfo->CalculateSimpleValue(i);
298 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
300 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
301 if(m_caster->GetTypeId() == TYPEID_PLAYER)
302 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
305 void Spell::EffectSchoolDMG(uint32 effect_idx)
307 if( unitTarget && unitTarget->isAlive())
309 switch(m_spellInfo->SpellFamilyName)
311 case SPELLFAMILY_GENERIC:
313 switch(m_spellInfo->Id) // better way to check unknown
315 // Meteor like spells (divided damage to targets)
316 case 24340: case 26558: case 28884: // Meteor
317 case 36837: case 38903: case 41276: // Meteor
318 case 26789: // Shard of the Fallen Star
319 case 31436: // Malevolent Cleave
320 case 35181: // Dive Bomb
321 case 40810: case 43267: case 43268: // Saber Lash
322 case 42384: // Brutal Swipe
323 case 45150: // Meteor Slash
324 case 64422: case 64688: // Sonic Screech
326 uint32 count = 0;
327 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
328 if(ihit->effectMask & (1<<effect_idx))
329 ++count;
331 damage /= count; // divide to all targets
332 break;
334 // percent from health with min
335 case 25599: // Thundercrash
337 damage = unitTarget->GetHealth() / 2;
338 if(damage < 200)
339 damage = 200;
340 break;
342 // Intercept (warrior spell trigger)
343 case 20253:
344 case 61491:
346 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
347 break;
349 // Cataclysmic Bolt
350 case 38441:
352 damage = unitTarget->GetMaxHealth() / 2;
353 break;
355 // Tympanic Tantrum
356 case 62775:
358 damage = unitTarget->GetMaxHealth() / 10;
359 break;
361 // Hand of Rekoning (name not have typos ;) )
362 case 67485:
363 damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
364 break;
366 break;
369 case SPELLFAMILY_MAGE:
371 // Arcane Blast
372 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
374 m_caster->CastSpell(m_caster, 36032, true);
376 break;
378 case SPELLFAMILY_WARRIOR:
380 // Bloodthirst
381 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
383 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
385 // Shield Slam
386 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
387 damage += int32(m_caster->GetShieldBlockValue());
388 // Victory Rush
389 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
391 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
392 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
394 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
395 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
396 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
397 // Heroic Throw ${$m1+$AP*.50}
398 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
399 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
400 // Shockwave ${$m3/100*$AP}
401 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
403 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
404 if (pct > 0)
405 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
406 break;
408 // Thunder Clap
409 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
411 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
413 break;
415 case SPELLFAMILY_WARLOCK:
417 // Incinerate Rank 1 & 2
418 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
420 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
421 // Check aura state for speed but aura state set not only for Immolate spell
422 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
424 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
425 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
427 // Immolate
428 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
429 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
431 damage += damage/4;
432 break;
437 // Shadowflame
438 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
440 // Apply DOT part
441 switch(m_spellInfo->Id)
443 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
444 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
445 default:
446 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
447 break;
450 // Conflagrate - consumes Immolate or Shadowflame
451 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
453 Aura const* aura = NULL; // found req. aura for damage calculation
455 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
456 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
458 // for caster applied auras only
459 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
460 (*i)->GetCasterGUID()!=m_caster->GetGUID())
461 continue;
463 // Immolate
464 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
466 aura = *i; // it selected always if exist
467 break;
470 // Shadowflame
471 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
472 aura = *i; // remember but wait possible Immolate as primary priority
475 // found Immolate or Shadowflame
476 if (aura)
478 int32 damagetick = aura->GetModifier()->m_amount;
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(1);
504 if (roll_chance_i(chance))
505 // Mind Trauma
506 m_caster->CastSpell(unitTarget, 48301, true, 0);
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[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 uint32 spellId = poison->GetId();
563 uint32 doses = poison->GetStackAmount();
564 if (doses > combo)
565 doses = combo;
566 for (int i=0; i< doses; i++)
567 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
568 damage *= doses;
569 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
571 // Eviscerate and Envenom Bonus Damage (item set effect)
572 if(m_caster->GetDummyAura(37169))
573 damage += ((Player*)m_caster)->GetComboPoints()*40;
576 // Eviscerate
577 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
579 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
581 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
582 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
584 // Eviscerate and Envenom Bonus Damage (item set effect)
585 if(m_caster->GetDummyAura(37169))
586 damage += combo*40;
589 // Gouge
590 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
592 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
594 // Instant Poison
595 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
597 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
599 // Wound Poison
600 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
602 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
604 break;
606 case SPELLFAMILY_HUNTER:
608 //Gore
609 if (m_spellInfo->SpellIconID == 1578)
611 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
612 damage *= 2;
614 // Mongoose Bite
615 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
617 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
619 // Counterattack
620 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
622 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
624 // Arcane Shot
625 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
627 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
629 // Steady Shot
630 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
632 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
633 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
635 // Explosive Trap Effect
636 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
638 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
640 break;
642 case SPELLFAMILY_PALADIN:
644 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
645 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
647 uint32 debuf_id;
648 switch(m_spellInfo->Id)
650 case 53733: debuf_id = 53742; break;// Judgement of Corruption -> Blood Corruption
651 case 31804: debuf_id = 31803; break;// Judgement of Vengeance -> Holy Vengeance
652 default: return;
655 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
656 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
657 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
658 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
659 // Get stack of Holy Vengeance on the target added by caster
660 uint32 stacks = 0;
661 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
662 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
664 if( ((*itr)->GetId() == debuf_id) && (*itr)->GetCasterGUID()==m_caster->GetGUID())
666 stacks = (*itr)->GetStackAmount();
667 break;
670 // + 10% for each application of Holy Vengeance on the target
671 if(stacks)
672 damage += damage * stacks * 10 /100;
674 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
675 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
677 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
678 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
679 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
680 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
682 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
683 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
685 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
686 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
687 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
688 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
690 // Hammer of the Righteous
691 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
693 // Add main hand dps * effect[2] amount
694 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
695 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
696 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
698 // Shield of Righteousness
699 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
701 damage+=int32(m_caster->GetShieldBlockValue());
703 // Judgement
704 else if (m_spellInfo->Id == 54158)
706 // [1 + 0.25 * SPH + 0.16 * AP]
707 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
709 break;
713 if(damage >= 0)
714 m_damage += damage;
718 void Spell::EffectDummy(uint32 i)
720 if (!unitTarget && !gameObjTarget && !itemTarget)
721 return;
723 // selection by spell family
724 switch(m_spellInfo->SpellFamilyName)
726 case SPELLFAMILY_GENERIC:
728 switch(m_spellInfo->Id )
730 case 8063: // Deviate Fish
732 if (m_caster->GetTypeId() != TYPEID_PLAYER)
733 return;
735 uint32 spell_id = 0;
736 switch(urand(1,5))
738 case 1: spell_id = 8064; break; // Sleepy
739 case 2: spell_id = 8065; break; // Invigorate
740 case 3: spell_id = 8066; break; // Shrink
741 case 4: spell_id = 8067; break; // Party Time!
742 case 5: spell_id = 8068; break; // Healthy Spirit
744 m_caster->CastSpell(m_caster, spell_id, true, NULL);
745 return;
747 case 8213: // Savory Deviate Delight
749 if (m_caster->GetTypeId() != TYPEID_PLAYER)
750 return;
752 uint32 spell_id = 0;
753 switch(urand(1,2))
755 // Flip Out - ninja
756 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
757 // Yaaarrrr - pirate
758 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
760 m_caster->CastSpell(m_caster,spell_id,true,NULL);
761 return;
763 case 8593: // Symbol of life (restore creature to life)
764 case 31225: // Shimmering Vessel (restore creature to life)
766 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
767 return;
768 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
769 return;
771 case 12162: // Deep wounds
772 case 12850: // (now good common check for this spells)
773 case 12868:
775 if (!unitTarget)
776 return;
778 float damage;
779 // DW should benefit of attack power, damage percent mods etc.
780 // TODO: check if using offhand damage is correct and if it should be divided by 2
781 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
782 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
783 else
784 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
786 switch (m_spellInfo->Id)
788 case 12162: damage *= 0.16f; break; // Rank 1
789 case 12850: damage *= 0.32f; break; // Rank 2
790 case 12868: damage *= 0.48f; break; // Rank 3
791 default:
792 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
793 return;
796 // get remaining damage of old Deep Wound aura
797 Aura* deepWound = unitTarget->GetAura(12721, 0);
798 if (deepWound)
800 int32 remainingTicks = deepWound->GetAuraDuration() / deepWound->GetModifier()->periodictime;
801 damage += remainingTicks * deepWound->GetModifier()->m_amount;
804 // 1 tick/sec * 6 sec = 6 ticks
805 int32 deepWoundsDotBasePoints0 = int32(damage / 6);
806 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
807 return;
809 case 13120: // net-o-matic
811 if (!unitTarget)
812 return;
814 uint32 spell_id = 0;
816 uint32 roll = urand(0, 99);
818 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
819 spell_id = 16566;
820 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
821 spell_id = 13119;
822 else // normal root
823 spell_id = 13099;
825 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
826 return;
828 case 13567: // Dummy Trigger
830 // can be used for different aura triggering, so select by aura
831 if (!m_triggeredByAuraSpell || !unitTarget)
832 return;
834 switch(m_triggeredByAuraSpell->Id)
836 case 26467: // Persistent Shield
837 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
838 break;
839 default:
840 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
841 break;
843 return;
845 case 15998: // Capture Worg Pup
846 case 29435: // Capture Female Kaliri Hatchling
848 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
849 return;
851 Creature* creatureTarget = (Creature*)unitTarget;
853 creatureTarget->ForcedDespawn();
854 return;
856 case 16589: // Noggenfogger Elixir
858 if (m_caster->GetTypeId() != TYPEID_PLAYER)
859 return;
861 uint32 spell_id = 0;
862 switch(urand(1, 3))
864 case 1: spell_id = 16595; break;
865 case 2: spell_id = 16593; break;
866 default:spell_id = 16591; break;
869 m_caster->CastSpell(m_caster, spell_id, true, NULL);
870 return;
872 case 17251: // Spirit Healer Res
874 if (!unitTarget || !m_originalCaster)
875 return;
877 if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
879 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
880 data << uint64(unitTarget->GetGUID());
881 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
883 return;
885 case 17271: // Test Fetid Skull
887 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
888 return;
890 uint32 spell_id = roll_chance_i(50)
891 ? 17269 // Create Resonating Skull
892 : 17270; // Create Bone Dust
894 m_caster->CastSpell(m_caster, spell_id, true, NULL);
895 return;
897 case 20577: // Cannibalize
898 if (unitTarget)
899 m_caster->CastSpell(m_caster, 20578, false, NULL);
900 return;
901 case 23019: // Crystal Prison Dummy DND
903 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
904 return;
906 Creature* creatureTarget = (Creature*)unitTarget;
907 if (creatureTarget->isPet())
908 return;
910 GameObject* pGameObj = new GameObject;
912 Map *map = creatureTarget->GetMap();
914 // create before death for get proper coordinates
915 if (!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
916 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
917 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
919 delete pGameObj;
920 return;
923 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
924 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
925 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
926 pGameObj->SetSpellId(m_spellInfo->Id);
928 creatureTarget->ForcedDespawn();
930 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
931 map->Add(pGameObj);
933 return;
935 case 23074: // Arcanite Dragonling
936 if (!m_CastItem)
937 return;
938 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
939 return;
940 case 23075: // Mithril Mechanical Dragonling
941 if (!m_CastItem)
942 return;
943 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
944 return;
945 case 23076: // Mechanical Dragonling
946 if (!m_CastItem)
947 return;
948 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
949 return;
950 case 23133: // Gnomish Battle Chicken
951 if (!m_CastItem)
952 return;
953 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
954 return;
955 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
957 int32 r = irand(0, 119);
958 if (r < 20) // Transporter Malfunction - 1/6 polymorph
959 m_caster->CastSpell(m_caster, 23444, true);
960 else if (r < 100) // Evil Twin - 4/6 evil twin
961 m_caster->CastSpell(m_caster, 23445, true);
962 else // Transporter Malfunction - 1/6 miss the target
963 m_caster->CastSpell(m_caster, 36902, true);
964 return;
966 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
967 if (roll_chance_i(50)) // Gadgetzan Transporter - success
968 m_caster->CastSpell(m_caster, 23441, true);
969 else // Gadgetzan Transporter Failure - failure
970 m_caster->CastSpell(m_caster, 23446, true);
971 return;
972 case 23645: // Hourglass Sand
973 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
974 return;
975 case 23725: // Gift of Life (warrior bwl trinket)
976 m_caster->CastSpell(m_caster, 23782, true);
977 m_caster->CastSpell(m_caster, 23783, true);
978 return;
979 case 25860: // Reindeer Transformation
981 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
982 return;
984 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
985 float speed = m_caster->GetSpeedRate(MOVE_RUN);
987 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
989 //5 different spells used depending on mounted speed and if mount can fly or not
990 if (flyspeed >= 4.1f)
991 // Flying Reindeer
992 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
993 else if (flyspeed >= 3.8f)
994 // Flying Reindeer
995 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
996 else if (flyspeed >= 1.6f)
997 // Flying Reindeer
998 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
999 else if (speed >= 2.0f)
1000 // Reindeer
1001 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
1002 else
1003 // Reindeer
1004 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
1006 return;
1008 case 26074: // Holiday Cheer
1009 // implemented at client side
1010 return;
1011 case 28006: // Arcane Cloaking
1013 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
1014 // Naxxramas Entry Flag Effect DND
1015 m_caster->CastSpell(unitTarget, 29294, true);
1016 return;
1018 case 29200: // Purify Helboar Meat
1020 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1021 return;
1023 uint32 spell_id = roll_chance_i(50)
1024 ? 29277 // Summon Purified Helboar Meat
1025 : 29278; // Summon Toxic Helboar Meat
1027 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1028 return;
1030 case 29858: // Soulshatter
1031 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
1032 m_caster->CastSpell(unitTarget,32835,true);
1033 return;
1034 case 30458: // Nigh Invulnerability
1035 if (!m_CastItem)
1036 return;
1037 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1038 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1039 else // Complete Vulnerability - backfire in 14% casts
1040 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1041 return;
1042 case 30507: // Poultryizer
1043 if(!m_CastItem)
1044 return;
1045 if (roll_chance_i(80)) // Poultryized! - success
1046 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1047 else // Poultryized! - backfire 20%
1048 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1049 return;
1050 case 33060: // Make a Wish
1052 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1053 return;
1055 uint32 spell_id = 0;
1057 switch(urand(1,5))
1059 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1060 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1061 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1062 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1063 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1066 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1067 return;
1069 case 34665: //Administer Antidote
1071 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1072 return;
1073 // Spell has scriptable target but for sure.
1074 if (unitTarget->GetTypeId() != TYPEID_UNIT)
1075 return;
1077 uint32 health = unitTarget->GetHealth();
1078 float x, y, z, o;
1080 unitTarget->GetPosition(x, y, z);
1081 o = unitTarget->GetOrientation();
1082 ((Creature*)unitTarget)->ForcedDespawn();
1084 if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000))
1086 summon->SetHealth(health);
1087 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon);
1089 if (summon->AI())
1090 summon->AI()->AttackStart(m_caster);
1092 return;
1094 case 35745: // Socrethar's Stone
1096 uint32 spell_id;
1097 switch(m_caster->GetAreaId())
1099 case 3900: spell_id = 35743; break; // Socrethar Portal
1100 case 3742: spell_id = 35744; break; // Socrethar Portal
1101 default: return;
1104 m_caster->CastSpell(m_caster, spell_id, true);
1105 return;
1107 case 37674: // Chaos Blast
1109 if (!unitTarget)
1110 return;
1112 int32 basepoints0 = 100;
1113 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1114 return;
1116 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1118 // selecting one from Bloodstained Fortune item
1119 uint32 newitemid;
1120 switch(urand(1, 20))
1122 case 1: newitemid = 32688; break;
1123 case 2: newitemid = 32689; break;
1124 case 3: newitemid = 32690; break;
1125 case 4: newitemid = 32691; break;
1126 case 5: newitemid = 32692; break;
1127 case 6: newitemid = 32693; break;
1128 case 7: newitemid = 32700; break;
1129 case 8: newitemid = 32701; break;
1130 case 9: newitemid = 32702; break;
1131 case 10: newitemid = 32703; break;
1132 case 11: newitemid = 32704; break;
1133 case 12: newitemid = 32705; break;
1134 case 13: newitemid = 32706; break;
1135 case 14: newitemid = 32707; break;
1136 case 15: newitemid = 32708; break;
1137 case 16: newitemid = 32709; break;
1138 case 17: newitemid = 32710; break;
1139 case 18: newitemid = 32711; break;
1140 case 19: newitemid = 32712; break;
1141 case 20: newitemid = 32713; break;
1142 default:
1143 return;
1146 DoCreateItem(i, newitemid);
1147 return;
1149 // Demon Broiled Surprise
1150 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1151 case 43723:
1153 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1154 return;
1156 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1157 return;
1160 case 44875: // Complete Raptor Capture
1162 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1163 return;
1165 Creature* creatureTarget = (Creature*)unitTarget;
1167 creatureTarget->ForcedDespawn();
1169 //cast spell Raptor Capture Credit
1170 m_caster->CastSpell(m_caster, 42337, true, NULL);
1171 return;
1173 case 44997: // Converting Sentry
1175 //Converted Sentry Credit
1176 m_caster->CastSpell(m_caster, 45009, true);
1177 return;
1179 case 45030: // Impale Emissary
1181 // Emissary of Hate Credit
1182 m_caster->CastSpell(m_caster, 45088, true);
1183 return;
1185 case 49357: // Brewfest Mount Transformation
1186 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1187 return;
1189 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1190 return;
1192 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1194 // Ram for Alliance, Kodo for Horde
1195 if (((Player *)m_caster)->GetTeam() == ALLIANCE)
1197 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1198 // 100% Ram
1199 m_caster->CastSpell(m_caster, 43900, true);
1200 else
1201 // 60% Ram
1202 m_caster->CastSpell(m_caster, 43899, true);
1204 else
1206 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1207 // 100% Kodo
1208 m_caster->CastSpell(m_caster, 49379, true);
1209 else
1210 // 60% Kodo
1211 m_caster->CastSpell(m_caster, 49378, true);
1213 return;
1214 case 50243: // Teach Language
1216 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1217 return;
1219 // spell has a 1/3 chance to trigger one of the below
1220 if (roll_chance_i(66))
1221 return;
1222 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1224 // 1000001 - gnomish binary
1225 m_caster->CastSpell(m_caster, 50242, true);
1227 else
1229 // 01001000 - goblin binary
1230 m_caster->CastSpell(m_caster, 50246, true);
1233 return;
1235 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1237 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1238 return;
1240 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1241 bg->EventPlayerDroppedFlag((Player*)m_caster);
1243 m_caster->CastSpell(m_caster, 30452, true, NULL);
1244 return;
1246 case 51592: // Pickup Primordial Hatchling
1248 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1249 return;
1251 Creature* creatureTarget = (Creature*)unitTarget;
1253 creatureTarget->ForcedDespawn();
1254 return;
1257 case 52308: // Take Sputum Sample
1259 switch(i)
1261 case 0:
1263 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1264 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1266 if (m_caster->HasAura(reqAuraID,0))
1267 m_caster->CastSpell(m_caster, spellID, true, NULL);
1268 return;
1270 case 1:
1271 return; // additional data for dummy[0]
1273 return;
1275 case 52759: // Ancestral Awakening
1276 if (!unitTarget)
1277 return;
1278 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1279 return;
1280 case 52845: // Brewfest Mount Transformation (Faction Swap)
1281 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1282 return;
1284 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1285 return;
1287 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1289 // Ram for Horde, Kodo for Alliance
1290 if (((Player *)m_caster)->GetTeam() == HORDE)
1292 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1293 // Swift Brewfest Ram, 100% Ram
1294 m_caster->CastSpell(m_caster, 43900, true);
1295 else
1296 // Brewfest Ram, 60% Ram
1297 m_caster->CastSpell(m_caster, 43899, true);
1299 else
1301 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1302 // Great Brewfest Kodo, 100% Kodo
1303 m_caster->CastSpell(m_caster, 49379, true);
1304 else
1305 // Brewfest Riding Kodo, 60% Kodo
1306 m_caster->CastSpell(m_caster, 49378, true);
1308 return;
1309 case 53341: // Rune of Cinderglacier
1310 case 53343: // Rune of Razorice
1312 // Runeforging Credit
1313 m_caster->CastSpell(m_caster, 54586, true);
1314 return;
1316 case 55004: // Nitro Boosts
1317 if (!m_CastItem)
1318 return;
1319 if (roll_chance_i(95)) // Nitro Boosts - success
1320 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1321 else // Knocked Up - backfire 5%
1322 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1323 return;
1324 case 58418: // Portal to Orgrimmar
1325 case 58420: // Portal to Stormwind
1326 return; // implemented in EffectScript[0]
1327 case 59640: // Underbelly Elixir
1329 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1330 return;
1332 uint32 spell_id = 0;
1333 switch(urand(1,3))
1335 case 1: spell_id = 59645; break;
1336 case 2: spell_id = 59831; break;
1337 case 3: spell_id = 59843; break;
1339 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1340 return;
1342 case 60932: // Disengage (one from creature versions)
1343 if (!unitTarget)
1344 return;
1345 m_caster->CastSpell(unitTarget,60934,true,NULL);
1346 return;
1347 case 67019: // Flask of the North
1349 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1350 return;
1352 uint32 spell_id = 0;
1353 switch(m_caster->getClass())
1355 case CLASS_WARRIOR:
1356 case CLASS_DEATH_KNIGHT:
1357 spell_id = 67018; // STR for Warriors, Death Knights
1358 break;
1359 case CLASS_ROGUE:
1360 case CLASS_HUNTER:
1361 spell_id = 67017; // AP for Rogues, Hunters
1362 break;
1363 case CLASS_PRIEST:
1364 case CLASS_MAGE:
1365 case CLASS_WARLOCK:
1366 spell_id = 67016; // SPD for Priests, Mages, Warlocks
1367 break;
1368 case CLASS_SHAMAN:
1369 // random (SPD, AP)
1370 spell_id = roll_chance_i(50) ? 67016 : 67017;
1371 break;
1372 case CLASS_PALADIN:
1373 case CLASS_DRUID:
1374 default:
1375 // random (SPD, STR)
1376 spell_id = roll_chance_i(50) ? 67016 : 67018;
1377 break;
1379 m_caster->CastSpell(m_caster, spell_id, true);
1380 return;
1383 break;
1385 case SPELLFAMILY_MAGE:
1386 switch(m_spellInfo->Id )
1388 case 11958: // Cold Snap
1390 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1391 return;
1393 // immediately finishes the cooldown on Frost spells
1394 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1395 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1397 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1399 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1400 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1401 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1403 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1405 else
1406 ++itr;
1408 return;
1410 case 32826: // Polymorph Cast Visual
1412 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1414 //Polymorph Cast Visual Rank 1
1415 const uint32 spell_list[6] = {
1416 32813, // Squirrel Form
1417 32816, // Giraffe Form
1418 32817, // Serpent Form
1419 32818, // Dragonhawk Form
1420 32819, // Worgen Form
1421 32820 // Sheep Form
1423 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1425 return;
1428 break;
1429 case SPELLFAMILY_WARRIOR:
1430 // Charge
1431 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1433 int32 chargeBasePoints0 = damage;
1434 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1435 return;
1437 // Execute
1438 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1440 if(!unitTarget)
1441 return;
1443 uint32 rage = m_caster->GetPower(POWER_RAGE);
1445 // up to max 30 rage cost
1446 if(rage > 300)
1447 rage = 300;
1449 // Glyph of Execution bonus
1450 uint32 rage_modified = rage;
1452 if (Aura *aura = m_caster->GetDummyAura(58367))
1453 rage_modified += aura->GetModifier()->m_amount*10;
1455 int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[i] +
1456 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1458 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1460 // Sudden Death
1461 if(m_caster->HasAura(52437))
1463 Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
1464 for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1466 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1467 if ((*itr)->GetSpellProto()->SpellIconID == 1989)
1469 // saved rage top stored in next affect
1470 uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(1)*10;
1471 if(lastrage < rage)
1472 rage -= lastrage;
1473 break;
1478 m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
1479 return;
1481 // Slam
1482 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1484 if(!unitTarget)
1485 return;
1486 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1487 m_damage+=damage;
1488 return;
1490 // Concussion Blow
1491 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1493 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1494 return;
1497 switch(m_spellInfo->Id)
1499 // Warrior's Wrath
1500 case 21977:
1502 if (!unitTarget)
1503 return;
1504 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1505 return;
1507 // Last Stand
1508 case 12975:
1510 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1511 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1512 return;
1514 // Bloodthirst
1515 case 23881:
1517 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1518 return;
1521 break;
1522 case SPELLFAMILY_WARLOCK:
1523 // Life Tap
1524 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1526 // In 303 exist spirit depend
1527 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1528 switch (m_spellInfo->Id)
1530 case 1454: damage+=spirit; break;
1531 case 1455: damage+=spirit*15/10; break;
1532 case 1456: damage+=spirit*2; break;
1533 case 11687: damage+=spirit*25/10; break;
1534 case 11688:
1535 case 11689:
1536 case 27222:
1537 case 57946: damage+=spirit*3; break;
1538 default:
1539 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1540 return;
1542 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1543 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1544 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1546 // Shouldn't Appear in Combat Log
1547 unitTarget->ModifyHealth(-damage);
1549 int32 mana = damage;
1550 // Improved Life Tap mod
1551 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1552 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1554 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1555 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1557 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1559 // Mana Feed
1560 int32 manaFeedVal = 0;
1561 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1562 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1564 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1565 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1567 if (manaFeedVal > 0)
1569 manaFeedVal = manaFeedVal * mana / 100;
1570 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1573 else
1574 SendCastResult(SPELL_FAILED_FIZZLE);
1575 return;
1577 break;
1578 case SPELLFAMILY_PRIEST:
1579 // Penance
1580 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1582 if (!unitTarget)
1583 return;
1585 int hurt = 0;
1586 int heal = 0;
1587 switch(m_spellInfo->Id)
1589 case 47540: hurt = 47758; heal = 47757; break;
1590 case 53005: hurt = 53001; heal = 52986; break;
1591 case 53006: hurt = 53002; heal = 52987; break;
1592 case 53007: hurt = 53003; heal = 52988; break;
1593 default:
1594 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1595 return;
1597 if (m_caster->IsFriendlyTo(unitTarget))
1598 m_caster->CastSpell(unitTarget, heal, true, 0);
1599 else
1600 m_caster->CastSpell(unitTarget, hurt, true, 0);
1601 return;
1603 break;
1604 case SPELLFAMILY_DRUID:
1605 // Starfall
1606 if (m_spellInfo->SpellFamilyFlags2 & UI64LIT(0x00000100))
1608 //Shapeshifting into an animal form or mounting cancels the effect.
1609 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1611 if(m_triggeredByAuraSpell)
1612 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1613 return;
1616 //Any effect which causes you to lose control of your character will supress the starfall effect.
1617 if (m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1618 return;
1620 switch(m_spellInfo->Id)
1622 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1623 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1624 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1625 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1626 default:
1627 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1628 return;
1631 break;
1632 case SPELLFAMILY_ROGUE:
1633 switch(m_spellInfo->Id )
1635 case 5938: // Shiv
1637 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1638 return;
1640 Player *pCaster = ((Player*)m_caster);
1642 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1643 if (!item)
1644 return;
1646 // all poison enchantments is temporary
1647 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1648 if (!enchant_id)
1649 return;
1651 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1652 if (!pEnchant)
1653 return;
1655 for (int s=0;s<3;s++)
1657 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1658 continue;
1660 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1661 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1662 continue;
1664 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1667 m_caster->CastSpell(unitTarget, 5940, true);
1668 return;
1670 case 14185: // Preparation
1672 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1673 return;
1675 //immediately finishes the cooldown on certain Rogue abilities
1676 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1677 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1679 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1681 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1682 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1683 else
1684 ++itr;
1686 return;
1688 case 31231: // Cheat Death
1690 m_caster->CastSpell(m_caster, 45182, true);
1691 return;
1694 break;
1695 case SPELLFAMILY_HUNTER:
1696 // Steady Shot
1697 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1699 if (!unitTarget || !unitTarget->isAlive())
1700 return;
1702 bool found = false;
1704 // check dazed affect
1705 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1706 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1708 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1710 found = true;
1711 break;
1715 if (found)
1716 m_damage+= damage;
1717 return;
1720 // Disengage
1721 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
1723 Unit* target = unitTarget;
1724 uint32 spellid;
1725 switch(m_spellInfo->Id)
1727 case 57635: spellid = 57636; break; // one from creature cases
1728 case 61507: spellid = 61508; break; // one from creature cases
1729 default:
1730 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
1731 return;
1733 if (!target || !target->isAlive())
1734 return;
1735 m_caster->CastSpell(target,spellid,true,NULL);
1738 switch(m_spellInfo->Id)
1740 case 23989: // Readiness talent
1742 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1743 return;
1745 //immediately finishes the cooldown for hunter abilities
1746 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
1747 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1749 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1751 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1752 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1753 else
1754 ++itr;
1756 return;
1758 case 37506: // Scatter Shot
1760 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1761 return;
1763 // break Auto Shot and autohit
1764 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1765 m_caster->AttackStop();
1766 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1767 return;
1769 // Last Stand
1770 case 53478:
1772 if (!unitTarget)
1773 return;
1774 int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
1775 unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1776 return;
1778 // Master's Call
1779 case 53271:
1781 Pet* pet = m_caster->GetPet();
1782 if (!pet || !unitTarget)
1783 return;
1785 pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(i), true);
1786 return;
1789 break;
1790 case SPELLFAMILY_PALADIN:
1791 switch(m_spellInfo->SpellIconID)
1793 case 156: // Holy Shock
1795 if (!unitTarget)
1796 return;
1798 int hurt = 0;
1799 int heal = 0;
1801 switch(m_spellInfo->Id)
1803 case 20473: hurt = 25912; heal = 25914; break;
1804 case 20929: hurt = 25911; heal = 25913; break;
1805 case 20930: hurt = 25902; heal = 25903; break;
1806 case 27174: hurt = 27176; heal = 27175; break;
1807 case 33072: hurt = 33073; heal = 33074; break;
1808 case 48824: hurt = 48822; heal = 48820; break;
1809 case 48825: hurt = 48823; heal = 48821; break;
1810 default:
1811 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1812 return;
1815 if (m_caster->IsFriendlyTo(unitTarget))
1816 m_caster->CastSpell(unitTarget, heal, true, 0);
1817 else
1818 m_caster->CastSpell(unitTarget, hurt, true, 0);
1820 return;
1822 case 561: // Judgement of command
1824 if (!unitTarget)
1825 return;
1827 uint32 spell_id = m_currentBasePoints[i]+1;
1828 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1829 if (!spell_proto)
1830 return;
1832 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1833 return;
1837 switch(m_spellInfo->Id)
1839 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1840 case 20187:
1842 if (!unitTarget)
1843 return;
1844 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1845 return;
1847 case 31789: // Righteous Defense (step 1)
1849 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1851 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1852 return;
1855 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1856 Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
1857 if (friendTarget)
1859 Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
1860 if (!player || !player->IsInSameRaidWith((Player*)m_caster))
1861 friendTarget = NULL;
1864 // non-standard cast requirement check
1865 if (!friendTarget || friendTarget->getAttackers().empty())
1867 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
1868 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1869 return;
1872 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1873 // Clear targets for eff 1
1874 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1875 ihit->effectMask &= ~(1<<1);
1877 // not empty (checked), copy
1878 Unit::AttackerSet attackers = friendTarget->getAttackers();
1880 // selected from list 3
1881 for(int i = 0; i < std::min(size_t(3),attackers.size()); ++i)
1883 Unit::AttackerSet::iterator aItr = attackers.begin();
1884 std::advance(aItr, rand() % attackers.size());
1885 AddUnitTarget((*aItr), 1);
1886 attackers.erase(aItr);
1889 // now let next effect cast spell at each target.
1890 return;
1892 case 37877: // Blessing of Faith
1894 if (!unitTarget)
1895 return;
1897 uint32 spell_id = 0;
1898 switch(unitTarget->getClass())
1900 case CLASS_DRUID: spell_id = 37878; break;
1901 case CLASS_PALADIN: spell_id = 37879; break;
1902 case CLASS_PRIEST: spell_id = 37880; break;
1903 case CLASS_SHAMAN: spell_id = 37881; break;
1904 default: return; // ignore for not healing classes
1907 m_caster->CastSpell(m_caster, spell_id, true);
1908 return;
1911 break;
1912 case SPELLFAMILY_SHAMAN:
1913 // Cleansing Totem
1914 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
1916 if (unitTarget)
1917 m_caster->CastSpell(unitTarget, 52025, true);
1918 return;
1920 // Healing Stream Totem
1921 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
1923 if (unitTarget)
1924 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1925 return;
1927 // Mana Spring Totem
1928 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
1930 if (!unitTarget || unitTarget->getPowerType()!=POWER_MANA)
1931 return;
1932 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1933 return;
1935 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
1937 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1938 return;
1939 // Glyph of Mana Tide
1940 if (Unit *owner = m_caster->GetOwner())
1941 if (Aura *dummy = owner->GetDummyAura(55441))
1942 damage+=dummy->GetModifier()->m_amount;
1943 // Regenerate 6% of Total Mana Every 3 secs
1944 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1945 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1946 return;
1948 // Lava Lash
1949 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1951 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1952 return;
1953 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1954 if (item)
1956 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1957 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1958 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1960 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1961 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
1962 (*itr)->GetCastItemGUID() == item->GetGUID())
1964 m_damage += m_damage * damage / 100;
1965 return;
1969 return;
1971 break;
1972 case SPELLFAMILY_DEATHKNIGHT:
1973 // Death Coil
1974 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
1976 if (m_caster->IsFriendlyTo(unitTarget))
1978 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1979 return;
1981 int32 bp = damage * 1.5f;
1982 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
1984 else
1986 int32 bp = damage;
1987 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
1989 return;
1991 // Hungering Cold
1992 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
1994 m_caster->CastSpell(m_caster, 51209, true);
1995 return;
1997 // Death Strike
1998 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
2000 uint32 count = 0;
2001 Unit::AuraMap const& auras = unitTarget->GetAuras();
2002 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2004 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
2005 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
2006 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
2008 ++count;
2009 // max. 15%
2010 if (count == 3)
2011 break;
2015 int32 bp = count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100;
2016 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
2017 return;
2019 break;
2022 // pet auras
2023 if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id, i))
2025 m_caster->AddPetAura(petSpell);
2026 return;
2029 // Script based implementation. Must be used only for not good for implementation in core spell effects
2030 // So called only for not proccessed cases
2031 if (gameObjTarget)
2032 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
2033 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
2034 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
2035 else if (itemTarget)
2036 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
2039 void Spell::EffectTriggerSpellWithValue(uint32 i)
2041 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2043 // normal case
2044 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2046 if(!spellInfo)
2048 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2049 return;
2052 int32 bp = damage;
2053 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
2056 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
2058 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2059 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2061 if(!spellInfo)
2063 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2064 return;
2067 finish();
2069 m_caster->CastSpell(unitTarget,spellInfo,false);
2072 void Spell::EffectForceCast(uint32 i)
2074 if( !unitTarget )
2075 return;
2077 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2079 // normal case
2080 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2082 if(!spellInfo)
2084 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2085 return;
2088 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2091 void Spell::EffectTriggerSpell(uint32 effIndex)
2093 // only unit case known
2094 if (!unitTarget)
2096 if(gameObjTarget || itemTarget)
2097 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
2098 return;
2101 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2103 // special cases
2104 switch(triggered_spell_id)
2106 // Vanish (not exist)
2107 case 18461:
2109 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2110 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2111 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2113 // if this spell is given to NPC it must handle rest by it's own AI
2114 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2115 return;
2117 // get highest rank of the Stealth spell
2118 uint32 spellId = 0;
2119 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2120 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2122 // only highest rank is shown in spell book, so simply check if shown in spell book
2123 if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
2124 continue;
2126 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2127 if (!spellInfo)
2128 continue;
2130 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2132 spellId = spellInfo->Id;
2133 break;
2137 // no Stealth spell found
2138 if (!spellId)
2139 return;
2141 // reset cooldown on it if needed
2142 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2143 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2145 m_caster->CastSpell(unitTarget, spellId, true);
2146 return;
2148 // just skip
2149 case 23770: // Sayge's Dark Fortune of *
2150 // not exist, common cooldown can be implemented in scripts if need.
2151 return;
2152 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2153 case 29284:
2155 // Brittle Armor
2156 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2157 if (!spell)
2158 return;
2160 for (int j=0; j < spell->StackAmount; ++j)
2161 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2162 return;
2164 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2165 case 29286:
2167 // Mercurial Shield
2168 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2169 if (!spell)
2170 return;
2172 for (int j=0; j < spell->StackAmount; ++j)
2173 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2174 return;
2176 // Righteous Defense
2177 case 31980:
2179 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2180 return;
2182 // Cloak of Shadows
2183 case 35729:
2185 Unit::AuraMap& Auras = unitTarget->GetAuras();
2186 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2188 // remove all harmful spells on you...
2189 if( // ignore positive and passive auras
2190 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2191 // ignore physical auras
2192 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2194 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2195 iter = Auras.begin();
2198 return;
2200 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2201 case 41967:
2203 if (Unit *pet = unitTarget->GetPet())
2204 pet->CastSpell(pet, 28305, true);
2205 return;
2209 // normal case
2210 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2211 if (!spellInfo)
2213 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2214 return;
2217 // select formal caster for triggered spell
2218 Unit* caster = m_caster;
2220 // some triggered spells require specific equipment
2221 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2223 // main hand weapon required
2224 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2226 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
2228 // skip spell if no weapon in slot or broken
2229 if (!item)
2230 return;
2232 // skip spell if weapon not fit to triggered spell
2233 if (!item->IsFitToSpellRequirements(spellInfo))
2234 return;
2237 // offhand hand weapon required
2238 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2240 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
2242 // skip spell if no weapon in slot or broken
2243 if (!item)
2244 return;
2246 // skip spell if weapon not fit to triggered spell
2247 if (!item->IsFitToSpellRequirements(spellInfo))
2248 return;
2251 else
2253 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2254 // so this just for speedup places in else
2255 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2258 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2261 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2263 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2265 // normal case
2266 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2268 if(!spellInfo)
2270 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2271 m_spellInfo->Id,effect_idx,triggered_spell_id);
2272 return;
2275 if (m_CastItem)
2276 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2278 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2281 void Spell::EffectJump(uint32 i)
2283 if(m_caster->isInFlight())
2284 return;
2286 // Init dest coordinates
2287 float x,y,z,o;
2288 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2290 x = m_targets.m_destX;
2291 y = m_targets.m_destY;
2292 z = m_targets.m_destZ;
2294 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2296 // explicit cast data from client or server-side cast
2297 // some spell at client send caster
2298 Unit* pTarget = NULL;
2299 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2300 pTarget = m_targets.getUnitTarget();
2301 else if(unitTarget->getVictim())
2302 pTarget = m_caster->getVictim();
2303 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2304 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2306 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2308 else
2309 o = m_caster->GetOrientation();
2311 else if(unitTarget)
2313 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2314 o = m_caster->GetOrientation();
2316 else if(gameObjTarget)
2318 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2319 o = m_caster->GetOrientation();
2321 else
2323 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2324 return;
2327 m_caster->NearTeleportTo(x, y, z, o, true);
2330 void Spell::EffectTeleportUnits(uint32 i)
2332 if(!unitTarget || unitTarget->isInFlight())
2333 return;
2335 switch (m_spellInfo->EffectImplicitTargetB[i])
2337 case TARGET_INNKEEPER_COORDINATES:
2339 // Only players can teleport to innkeeper
2340 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2341 return;
2343 ((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
2344 return;
2346 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2347 case TARGET_TABLE_X_Y_Z_COORDINATES:
2349 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
2350 if(!st)
2352 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2353 return;
2356 if(st->target_mapId==unitTarget->GetMapId())
2357 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2358 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2359 ((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);
2360 break;
2362 case TARGET_BEHIND_VICTIM:
2364 Unit *pTarget = NULL;
2366 // explicit cast data from client or server-side cast
2367 // some spell at client send caster
2368 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2369 pTarget = m_targets.getUnitTarget();
2370 else if(unitTarget->getVictim())
2371 pTarget = unitTarget->getVictim();
2372 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2373 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2375 // Init dest coordinates
2376 float x = m_targets.m_destX;
2377 float y = m_targets.m_destY;
2378 float z = m_targets.m_destZ;
2379 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2380 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2381 return;
2383 default:
2385 // If not exist data for dest location - return
2386 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2388 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2389 return;
2391 // Init dest coordinates
2392 float x = m_targets.m_destX;
2393 float y = m_targets.m_destY;
2394 float z = m_targets.m_destZ;
2395 float orientation = unitTarget->GetOrientation();
2396 // Teleport
2397 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2398 return;
2402 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2403 switch ( m_spellInfo->Id )
2405 // Dimensional Ripper - Everlook
2406 case 23442:
2408 int32 r = irand(0, 119);
2409 if ( r >= 70 ) // 7/12 success
2411 if ( r < 100 ) // 4/12 evil twin
2412 m_caster->CastSpell(m_caster, 23445, true);
2413 else // 1/12 fire
2414 m_caster->CastSpell(m_caster, 23449, true);
2416 return;
2418 // Ultrasafe Transporter: Toshley's Station
2419 case 36941:
2421 if ( roll_chance_i(50) ) // 50% success
2423 int32 rand_eff = urand(1, 7);
2424 switch ( rand_eff )
2426 case 1:
2427 // soul split - evil
2428 m_caster->CastSpell(m_caster, 36900, true);
2429 break;
2430 case 2:
2431 // soul split - good
2432 m_caster->CastSpell(m_caster, 36901, true);
2433 break;
2434 case 3:
2435 // Increase the size
2436 m_caster->CastSpell(m_caster, 36895, true);
2437 break;
2438 case 4:
2439 // Decrease the size
2440 m_caster->CastSpell(m_caster, 36893, true);
2441 break;
2442 case 5:
2443 // Transform
2445 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2446 m_caster->CastSpell(m_caster, 36897, true);
2447 else
2448 m_caster->CastSpell(m_caster, 36899, true);
2449 break;
2451 case 6:
2452 // chicken
2453 m_caster->CastSpell(m_caster, 36940, true);
2454 break;
2455 case 7:
2456 // evil twin
2457 m_caster->CastSpell(m_caster, 23445, true);
2458 break;
2461 return;
2463 // Dimensional Ripper - Area 52
2464 case 36890:
2466 if ( roll_chance_i(50) ) // 50% success
2468 int32 rand_eff = urand(1, 4);
2469 switch ( rand_eff )
2471 case 1:
2472 // soul split - evil
2473 m_caster->CastSpell(m_caster, 36900, true);
2474 break;
2475 case 2:
2476 // soul split - good
2477 m_caster->CastSpell(m_caster, 36901, true);
2478 break;
2479 case 3:
2480 // Increase the size
2481 m_caster->CastSpell(m_caster, 36895, true);
2482 break;
2483 case 4:
2484 // Transform
2486 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2487 m_caster->CastSpell(m_caster, 36897, true);
2488 else
2489 m_caster->CastSpell(m_caster, 36899, true);
2490 break;
2494 return;
2499 void Spell::EffectApplyAura(uint32 i)
2501 if(!unitTarget)
2502 return;
2504 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2505 if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) &&
2506 (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2507 return;
2509 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2510 if(!caster)
2511 return;
2513 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2515 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2517 // Now Reduce spell duration using data received at spell hit
2518 int32 duration = Aur->GetAuraMaxDuration();
2519 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2520 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2521 Aur->setDiminishGroup(m_diminishGroup);
2523 // if Aura removed and deleted, do not continue.
2524 if(duration== 0 && !(Aur->IsPermanent()))
2526 delete Aur;
2527 return;
2530 if(duration != Aur->GetAuraMaxDuration())
2532 Aur->SetAuraMaxDuration(duration);
2533 Aur->SetAuraDuration(duration);
2536 unitTarget->AddAura(Aur);
2539 void Spell::EffectUnlearnSpecialization( uint32 i )
2541 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2542 return;
2544 Player *_player = (Player*)unitTarget;
2545 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2547 _player->removeSpell(spellToUnlearn);
2549 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2552 void Spell::EffectPowerDrain(uint32 i)
2554 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2555 return;
2557 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2559 if(!unitTarget)
2560 return;
2561 if(!unitTarget->isAlive())
2562 return;
2563 if(unitTarget->getPowerType() != drain_power)
2564 return;
2565 if(damage < 0)
2566 return;
2568 uint32 curPower = unitTarget->GetPower(drain_power);
2570 //add spell damage bonus
2571 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2573 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2574 uint32 power = damage;
2575 if (drain_power == POWER_MANA)
2576 power -= unitTarget->GetSpellCritDamageReduction(power);
2578 int32 new_damage;
2579 if(curPower < power)
2580 new_damage = curPower;
2581 else
2582 new_damage = power;
2584 unitTarget->ModifyPower(drain_power,-new_damage);
2586 // Don`t restore from self drain
2587 if(drain_power == POWER_MANA && m_caster != unitTarget)
2589 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2590 if(manaMultiplier==0)
2591 manaMultiplier = 1;
2593 if(Player *modOwner = m_caster->GetSpellModOwner())
2594 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2596 int32 gain = int32(new_damage * manaMultiplier);
2598 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2602 void Spell::EffectSendEvent(uint32 EffectIndex)
2605 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2607 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2608 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2611 void Spell::EffectPowerBurn(uint32 i)
2613 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2614 return;
2616 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2618 if (!unitTarget)
2619 return;
2620 if (!unitTarget->isAlive())
2621 return;
2622 if (unitTarget->getPowerType()!=powertype)
2623 return;
2624 if (damage < 0)
2625 return;
2627 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2628 if (m_spellInfo->ManaCostPercentage)
2630 uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2631 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2632 if(damage > maxdamage) damage = maxdamage;
2635 int32 curPower = int32(unitTarget->GetPower(powertype));
2637 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2638 uint32 power = damage;
2639 if (powertype == POWER_MANA)
2640 power -= unitTarget->GetSpellCritDamageReduction(power);
2642 int32 new_damage = (curPower < power) ? curPower : power;
2644 unitTarget->ModifyPower(powertype, -new_damage);
2645 float multiplier = m_spellInfo->EffectMultipleValue[i];
2647 if (Player *modOwner = m_caster->GetSpellModOwner())
2648 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2650 new_damage = int32(new_damage * multiplier);
2651 m_damage += new_damage;
2654 void Spell::EffectHeal( uint32 /*i*/ )
2656 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2658 // Try to get original caster
2659 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2661 // Skip if m_originalCaster not available
2662 if (!caster)
2663 return;
2665 int32 addhealth = damage;
2667 // Vessel of the Naaru (Vial of the Sunwell trinket)
2668 if (m_spellInfo->Id == 45064)
2670 // Amount of heal - depends from stacked Holy Energy
2671 int damageAmount = 0;
2672 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2673 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2674 if ((*i)->GetId() == 45062)
2675 damageAmount+=(*i)->GetModifier()->m_amount;
2676 if (damageAmount)
2677 m_caster->RemoveAurasDueToSpell(45062);
2679 addhealth += damageAmount;
2681 // Death Pact (percent heal)
2682 else if (m_spellInfo->Id==48743)
2683 addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
2684 // Swiftmend - consumes Regrowth or Rejuvenation
2685 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2687 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2688 // find most short by duration
2689 Aura *targetAura = NULL;
2690 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2692 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2693 // Regrowth or Rejuvenation 0x40 | 0x10
2694 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
2696 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2697 targetAura = *i;
2701 if (!targetAura)
2703 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
2704 return;
2706 int idx = 0;
2707 while(idx < 3)
2709 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2710 break;
2711 idx++;
2714 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2715 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2717 // Glyph of Swiftmend
2718 if (!caster->HasAura(54824))
2719 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2721 addhealth += tickheal * tickcount;
2723 else
2724 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2726 m_healing+=addhealth;
2730 void Spell::EffectHealPct( uint32 /*i*/ )
2732 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2734 // Try to get original caster
2735 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2737 // Skip if m_originalCaster not available
2738 if (!caster)
2739 return;
2741 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2742 if (Player* modOwner = m_caster->GetSpellModOwner())
2743 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2745 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2746 unitTarget->getHostileRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2750 void Spell::EffectHealMechanical( uint32 /*i*/ )
2752 // Mechanic creature type should be correctly checked by targetCreatureType field
2753 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2755 // Try to get original caster
2756 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2758 // Skip if m_originalCaster not available
2759 if (!caster)
2760 return;
2762 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2763 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2767 void Spell::EffectHealthLeech(uint32 i)
2769 if (!unitTarget)
2770 return;
2771 if (!unitTarget->isAlive())
2772 return;
2774 if (damage < 0)
2775 return;
2777 sLog.outDebug("HealthLeech :%i", damage);
2779 uint32 curHealth = unitTarget->GetHealth();
2780 damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
2781 if (curHealth < damage)
2782 damage = curHealth;
2784 float multiplier = m_spellInfo->EffectMultipleValue[i];
2786 if (Player *modOwner = m_caster->GetSpellModOwner())
2787 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2789 uint32 heal = uint32(damage*multiplier);
2790 if (m_caster->isAlive())
2792 heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
2793 m_caster->DealHeal(m_caster, heal, m_spellInfo);
2797 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2799 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2800 return;
2802 Player* player = (Player*)unitTarget;
2804 uint32 newitemid = itemtype;
2805 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype( newitemid );
2806 if(!pProto)
2808 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2809 return;
2812 // bg reward have some special in code work
2813 uint32 bgType = 0;
2814 switch(m_spellInfo->Id)
2816 case SPELL_AV_MARK_WINNER:
2817 case SPELL_AV_MARK_LOSER:
2818 bgType = BATTLEGROUND_AV;
2819 break;
2820 case SPELL_WS_MARK_WINNER:
2821 case SPELL_WS_MARK_LOSER:
2822 bgType = BATTLEGROUND_WS;
2823 break;
2824 case SPELL_AB_MARK_WINNER:
2825 case SPELL_AB_MARK_LOSER:
2826 bgType = BATTLEGROUND_AB;
2827 break;
2828 default:
2829 break;
2832 uint32 num_to_add;
2834 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2835 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2837 int32 basePoints = m_currentBasePoints[i];
2838 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2839 if (randomPoints)
2840 num_to_add = basePoints + irand(1, randomPoints);
2841 else
2842 num_to_add = basePoints + 1;
2844 else if (pProto->MaxCount == 1)
2845 num_to_add = 1;
2846 else if(player->getLevel() >= m_spellInfo->spellLevel)
2848 int32 basePoints = m_currentBasePoints[i];
2849 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2850 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2852 else
2853 num_to_add = 2;
2855 if (num_to_add < 1)
2856 num_to_add = 1;
2857 if (num_to_add > pProto->GetMaxStackSize())
2858 num_to_add = pProto->GetMaxStackSize();
2860 // init items_count to 1, since 1 item will be created regardless of specialization
2861 int items_count=1;
2862 // the chance to create additional items
2863 float additionalCreateChance=0.0f;
2864 // the maximum number of created additional items
2865 uint8 additionalMaxNum=0;
2866 // get the chance and maximum number for creating extra items
2867 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2869 // roll with this chance till we roll not to create or we create the max num
2870 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2871 ++items_count;
2874 // really will be created more items
2875 num_to_add *= items_count;
2877 // can the player store the new item?
2878 ItemPosCountVec dest;
2879 uint32 no_space = 0;
2880 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2881 if( msg != EQUIP_ERR_OK )
2883 // convert to possible store amount
2884 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2885 num_to_add -= no_space;
2886 else
2888 // if not created by another reason from full inventory or unique items amount limitation
2889 player->SendEquipError( msg, NULL, NULL );
2890 return;
2894 if(num_to_add)
2896 // create the new item and store it
2897 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2899 // was it successful? return error if not
2900 if(!pItem)
2902 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2903 return;
2906 // set the "Crafted by ..." property of the item
2907 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2908 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
2910 // send info to the client
2911 if(pItem)
2912 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
2914 // we succeeded in creating at least one item, so a levelup is possible
2915 if(bgType == 0)
2916 player->UpdateCraftSkill(m_spellInfo->Id);
2919 // for battleground marks send by mail if not add all expected
2920 if(no_space > 0 && bgType)
2922 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
2923 bg->SendRewardMarkByMail(player, newitemid, no_space);
2927 void Spell::EffectCreateItem(uint32 i)
2929 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2932 void Spell::EffectCreateItem2(uint32 i)
2934 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2935 return;
2936 Player* player = (Player*)m_caster;
2938 uint32 item_id = m_spellInfo->EffectItemType[i];
2940 DoCreateItem(i, item_id);
2942 // special case: fake item replaced by generate using spell_loot_template
2943 if (IsLootCraftingSpell(m_spellInfo))
2945 if (!player->HasItemCount(item_id, 1))
2946 return;
2948 // remove reagent
2949 uint32 count = 1;
2950 player->DestroyItemCount(item_id, count, true);
2952 // create some random items
2953 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2957 void Spell::EffectCreateRandomItem(uint32 i)
2959 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2960 return;
2961 Player* player = (Player*)m_caster;
2963 // create some random items
2964 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2967 void Spell::EffectPersistentAA(uint32 i)
2969 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2971 if (Player* modOwner = m_caster->GetSpellModOwner())
2972 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2974 int32 duration = GetSpellDuration(m_spellInfo);
2975 DynamicObject* dynObj = new DynamicObject;
2976 if (!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2978 delete dynObj;
2979 return;
2981 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2982 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2983 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2984 m_caster->AddDynObject(dynObj);
2985 m_caster->GetMap()->Add(dynObj);
2988 void Spell::EffectEnergize(uint32 i)
2990 if(!unitTarget)
2991 return;
2992 if(!unitTarget->isAlive())
2993 return;
2995 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2996 return;
2998 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
3000 // Some level depends spells
3001 int level_multiplier = 0;
3002 int level_diff = 0;
3003 switch (m_spellInfo->Id)
3005 case 9512: // Restore Energy
3006 level_diff = m_caster->getLevel() - 40;
3007 level_multiplier = 2;
3008 break;
3009 case 24571: // Blood Fury
3010 level_diff = m_caster->getLevel() - 60;
3011 level_multiplier = 10;
3012 break;
3013 case 24532: // Burst of Energy
3014 level_diff = m_caster->getLevel() - 60;
3015 level_multiplier = 4;
3016 break;
3017 case 31930: // Judgements of the Wise
3018 case 63375: // Improved Stormstrike
3019 damage = damage * unitTarget->GetCreateMana() / 100;
3020 break;
3021 default:
3022 break;
3025 if (level_diff > 0)
3026 damage -= level_multiplier * level_diff;
3028 if(damage < 0)
3029 return;
3031 if(unitTarget->GetMaxPower(power) == 0)
3032 return;
3034 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
3036 // Mad Alchemist's Potion
3037 if (m_spellInfo->Id == 45051)
3039 // find elixirs on target
3040 uint32 elixir_mask = 0;
3041 Unit::AuraMap& Auras = unitTarget->GetAuras();
3042 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3044 uint32 spell_id = itr->second->GetId();
3045 if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
3046 elixir_mask |= mask;
3049 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3050 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
3052 // get all available elixirs by mask and spell level
3053 std::vector<uint32> elixirs;
3054 SpellElixirMap const& m_spellElixirs = sSpellMgr.GetSpellElixirMap();
3055 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
3057 if (itr->second & elixir_mask)
3059 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
3060 continue;
3062 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
3063 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
3064 continue;
3066 elixirs.push_back(itr->first);
3070 if (!elixirs.empty())
3072 // cast random elixir on target
3073 uint32 rand_spell = urand(0,elixirs.size()-1);
3074 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
3079 void Spell::EffectEnergisePct(uint32 i)
3081 if (!unitTarget)
3082 return;
3083 if (!unitTarget->isAlive())
3084 return;
3086 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
3087 return;
3089 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
3091 uint32 maxPower = unitTarget->GetMaxPower(power);
3092 if (maxPower == 0)
3093 return;
3095 uint32 gain = damage * maxPower / 100;
3096 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
3099 void Spell::SendLoot(uint64 guid, LootType loottype)
3101 Player* player = (Player*)m_caster;
3102 if (!player)
3103 return;
3105 if (gameObjTarget)
3107 if (Script->GOHello(player, gameObjTarget))
3108 return;
3110 switch (gameObjTarget->GetGoType())
3112 case GAMEOBJECT_TYPE_DOOR:
3113 case GAMEOBJECT_TYPE_BUTTON:
3114 gameObjTarget->UseDoorOrButton();
3115 player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
3116 return;
3118 case GAMEOBJECT_TYPE_QUESTGIVER:
3119 // start or end quest
3120 player->PrepareQuestMenu(guid);
3121 player->SendPreparedQuest(guid);
3122 return;
3124 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3125 // triggering linked GO
3126 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
3127 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3128 return;
3130 case GAMEOBJECT_TYPE_GOOBER:
3131 // goober_scripts can be triggered if the player don't have the quest
3132 if (gameObjTarget->GetGOInfo()->goober.eventId)
3134 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
3135 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
3138 // cast goober spell
3139 if (gameObjTarget->GetGOInfo()->goober.questId)
3140 ///Quest require to be active for GO using
3141 if (player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
3142 return;
3144 gameObjTarget->AddUniqueUse(player);
3145 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
3147 //TODO? Objective counting called without spell check but with quest objective check
3148 // if send spell id then this line will duplicate to spell casting call (double counting)
3149 // So we or have this line and not required in quest_template have reqSpellIdN
3150 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3151 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
3153 // triggering linked GO
3154 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
3155 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3157 return;
3159 case GAMEOBJECT_TYPE_CHEST:
3160 // TODO: possible must be moved to loot release (in different from linked triggering)
3161 if (gameObjTarget->GetGOInfo()->chest.eventId)
3163 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
3164 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
3167 // triggering linked GO
3168 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
3169 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3171 // Don't return, let loots been taken
3172 default:
3173 break;
3177 // Send loot
3178 player->SendLoot(guid, loottype);
3181 void Spell::EffectOpenLock(uint32 effIndex)
3183 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3185 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3186 return;
3189 Player* player = (Player*)m_caster;
3191 uint32 lockId = 0;
3192 uint64 guid = 0;
3194 // Get lockId
3195 if (gameObjTarget)
3197 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3198 // Arathi Basin banner opening !
3199 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3200 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3202 //CanUseBattleGroundObject() already called in CheckCast()
3203 // in battleground check
3204 if (BattleGround *bg = player->GetBattleGround())
3206 // check if it's correct bg
3207 if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
3208 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3209 return;
3212 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3214 //CanUseBattleGroundObject() already called in CheckCast()
3215 // in battleground check
3216 if (BattleGround *bg = player->GetBattleGround())
3218 if (bg->GetTypeID() == BATTLEGROUND_EY)
3219 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3220 return;
3223 lockId = goInfo->GetLockId();
3224 guid = gameObjTarget->GetGUID();
3226 else if (itemTarget)
3228 lockId = itemTarget->GetProto()->LockID;
3229 guid = itemTarget->GetGUID();
3231 else
3233 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3234 return;
3237 SkillType skillId = SKILL_NONE;
3238 int32 reqSkillValue = 0;
3239 int32 skillValue;
3241 SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
3242 if (res != SPELL_CAST_OK)
3244 SendCastResult(res);
3245 return;
3248 SendLoot(guid, LOOT_SKINNING);
3250 // not allow use skill grow at item base open
3251 if (!m_CastItem && skillId != SKILL_NONE)
3253 // update skill if really known
3254 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3256 if (gameObjTarget)
3258 // Allow one skill-up until respawned
3259 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3260 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3261 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3263 else if (itemTarget)
3265 // Do one skill-up
3266 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3272 void Spell::EffectSummonChangeItem(uint32 i)
3274 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3275 return;
3277 Player *player = (Player*)m_caster;
3279 // applied only to using item
3280 if (!m_CastItem)
3281 return;
3283 // ... only to item in own inventory/bank/equip_slot
3284 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3285 return;
3287 uint32 newitemid = m_spellInfo->EffectItemType[i];
3288 if (!newitemid)
3289 return;
3291 uint16 pos = m_CastItem->GetPos();
3293 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3294 if (!pNewItem)
3295 return;
3297 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3299 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3300 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3303 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3305 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3306 player->DurabilityLoss(pNewItem, loosePercent);
3309 if (player->IsInventoryPos(pos))
3311 ItemPosCountVec dest;
3312 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3313 if (msg == EQUIP_ERR_OK)
3315 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3317 // prevent crash at access and unexpected charges counting with item update queue corrupt
3318 if (m_CastItem==m_targets.getItemTarget())
3319 m_targets.setItemTarget(NULL);
3321 m_CastItem = NULL;
3323 player->StoreItem( dest, pNewItem, true);
3324 return;
3327 else if (player->IsBankPos (pos))
3329 ItemPosCountVec dest;
3330 uint8 msg = player->CanBankItem( 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->BankItem( dest, pNewItem, true);
3342 return;
3345 else if (player->IsEquipmentPos (pos))
3347 uint16 dest;
3348 uint8 msg = player->CanEquipItem( 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->EquipItem( dest, pNewItem, true);
3360 player->AutoUnequipOffhandIfNeed();
3361 return;
3365 // fail
3366 delete pNewItem;
3369 void Spell::EffectProficiency(uint32 /*i*/)
3371 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3372 return;
3373 Player *p_target = (Player*)unitTarget;
3375 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3376 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3378 p_target->AddWeaponProficiency(subClassMask);
3379 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3381 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3383 p_target->AddArmorProficiency(subClassMask);
3384 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3388 void Spell::EffectApplyAreaAura(uint32 i)
3390 if (!unitTarget)
3391 return;
3392 if (!unitTarget->isAlive())
3393 return;
3395 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3396 unitTarget->AddAura(Aur);
3399 void Spell::EffectSummonType(uint32 i)
3401 uint32 prop_id = m_spellInfo->EffectMiscValueB[i];
3402 SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
3403 if(!summon_prop)
3405 sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3406 return;
3409 switch(summon_prop->Group)
3411 // faction handled later on, or loaded from template
3412 case SUMMON_PROP_GROUP_WILD:
3413 case SUMMON_PROP_GROUP_FRIENDLY:
3415 switch(summon_prop->Type)
3417 case SUMMON_PROP_TYPE_OTHER:
3419 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3420 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3421 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3422 if(prop_id == 121 || prop_id == 647)
3423 EffectSummonTotem(i);
3424 else
3425 EffectSummonWild(i, summon_prop->FactionId);
3426 break;
3428 case SUMMON_PROP_TYPE_SUMMON:
3429 case SUMMON_PROP_TYPE_GUARDIAN:
3430 case SUMMON_PROP_TYPE_ARMY:
3431 case SUMMON_PROP_TYPE_DK:
3432 case SUMMON_PROP_TYPE_CONSTRUCT:
3434 // JC golems - 32804, etc -- fits much better totem AI
3435 if(m_spellInfo->SpellIconID == 2056)
3436 EffectSummonTotem(i);
3437 if(prop_id == 832) // scrapbot
3438 EffectSummonWild(i, summon_prop->FactionId);
3439 else
3440 EffectSummonGuardian(i, summon_prop->FactionId);
3441 break;
3443 case SUMMON_PROP_TYPE_TOTEM:
3444 EffectSummonTotem(i, summon_prop->Slot);
3445 break;
3446 case SUMMON_PROP_TYPE_CRITTER:
3447 EffectSummonCritter(i, summon_prop->FactionId);
3448 break;
3449 case SUMMON_PROP_TYPE_PHASING:
3450 case SUMMON_PROP_TYPE_LIGHTWELL:
3451 case SUMMON_PROP_TYPE_REPAIR_BOT:
3452 EffectSummonWild(i, summon_prop->FactionId);
3453 break;
3454 case SUMMON_PROP_TYPE_SIEGE_VEH:
3455 case SUMMON_PROP_TYPE_DRAKE_VEH:
3456 // TODO
3457 // EffectSummonVehicle(i);
3458 break;
3459 default:
3460 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
3461 break;
3463 break;
3465 case SUMMON_PROP_GROUP_PETS:
3467 // FIXME : multiple summons - not yet supported as pet
3468 //1562 - force of nature - sid 33831
3469 //1161 - feral spirit - sid 51533
3470 if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
3471 EffectSummonGuardian(i, summon_prop->FactionId);
3472 else
3473 EffectSummon(i);
3474 break;
3476 case SUMMON_PROP_GROUP_CONTROLLABLE:
3478 // no type here
3479 // maybe wrong - but thats the handler currently used for those
3480 EffectSummonGuardian(i, summon_prop->FactionId);
3481 break;
3483 case SUMMON_PROP_GROUP_VEHICLE:
3485 // TODO
3486 // EffectSummonVehicle(i);
3487 break;
3489 default:
3490 sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
3491 break;
3495 void Spell::EffectSummon(uint32 i)
3497 if (m_caster->GetPetGUID())
3498 return;
3500 if (!unitTarget)
3501 return;
3502 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3503 if (!pet_entry)
3504 return;
3505 uint32 level = m_caster->getLevel();
3506 Pet* spawnCreature = new Pet(SUMMON_PET);
3508 int32 duration = GetSpellDuration(m_spellInfo);
3509 if(Player* modOwner = m_caster->GetSpellModOwner())
3510 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3512 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3514 // Summon in dest location
3515 float x, y, z;
3516 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3518 x = m_targets.m_destX;
3519 y = m_targets.m_destY;
3520 z = m_targets.m_destZ;
3521 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3524 // set timer for unsummon
3525 if (duration > 0)
3526 spawnCreature->SetDuration(duration);
3528 return;
3531 Map *map = m_caster->GetMap();
3532 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3533 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3534 m_spellInfo->EffectMiscValue[i], pet_number))
3536 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3537 delete spawnCreature;
3538 return;
3541 // Summon in dest location
3542 float x, y, z;
3543 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3545 x = m_targets.m_destX;
3546 y = m_targets.m_destY;
3547 z = m_targets.m_destZ;
3549 else
3550 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3552 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3554 if (!spawnCreature->IsPositionValid())
3556 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3557 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3558 delete spawnCreature;
3559 return;
3562 // set timer for unsummon
3563 if (duration > 0)
3564 spawnCreature->SetDuration(duration);
3566 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3567 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3568 spawnCreature->setPowerType(POWER_MANA);
3569 spawnCreature->setFaction(m_caster->getFaction());
3570 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3571 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3572 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3573 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3574 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3575 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3576 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3577 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3579 spawnCreature->InitStatsForLevel(level, m_caster);
3581 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3583 spawnCreature->AIM_Initialize();
3584 spawnCreature->InitPetCreateSpells();
3585 spawnCreature->InitLevelupSpellsForLevel();
3586 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3587 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3589 std::string name = m_caster->GetName();
3590 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3591 spawnCreature->SetName( name );
3593 map->Add((Creature*)spawnCreature);
3595 m_caster->SetPet(spawnCreature);
3597 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3599 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3600 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3601 ((Player*)m_caster)->PetSpellInitialize();
3605 void Spell::EffectLearnSpell(uint32 i)
3607 if (!unitTarget)
3608 return;
3610 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3612 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3613 EffectLearnPetSpell(i);
3615 return;
3618 Player *player = (Player*)unitTarget;
3620 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3621 player->learnSpell(spellToLearn,false);
3623 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3626 void Spell::EffectDispel(uint32 i)
3628 if (!unitTarget)
3629 return;
3631 // Fill possible dispell list
3632 std::vector <Aura *> dispel_list;
3634 // Create dispel mask by dispel type
3635 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3636 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3637 Unit::AuraMap const& auras = unitTarget->GetAuras();
3638 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3640 Aura *aur = (*itr).second;
3641 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3643 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3645 bool positive = true;
3646 if (!aur->IsPositive())
3647 positive = false;
3648 else
3649 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3651 // do not remove positive auras if friendly target
3652 // negative auras if non-friendly target
3653 if (positive == unitTarget->IsFriendlyTo(m_caster))
3654 continue;
3656 // Add aura to dispel list (all stack cases)
3657 for(int k = 0; k < aur->GetStackAmount(); ++k)
3658 dispel_list.push_back(aur);
3661 // Ok if exist some buffs for dispel try dispel it
3662 if (!dispel_list.empty())
3664 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3665 std::list < uint32 > fail_list; // spell_id
3667 // some spells have effect value = 0 and all from its by meaning expect 1
3668 if(!damage)
3669 damage = 1;
3671 // Dispell N = damage buffs (or while exist buffs for dispel)
3672 for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
3674 // Random select buff for dispel
3675 std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
3676 std::advance(dispel_itr,urand(0, dispel_list.size()-1));
3678 Aura *aur = *dispel_itr;
3680 // remove entry from dispel_list
3681 dispel_list.erase(dispel_itr);
3683 SpellEntry const* spellInfo = aur->GetSpellProto();
3684 // Base dispel chance
3685 // TODO: possible chance depend from spell level??
3686 int32 miss_chance = 0;
3687 // Apply dispel mod from aura caster
3688 if (Unit *caster = aur->GetCaster())
3690 if ( Player* modOwner = caster->GetSpellModOwner() )
3691 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3693 // Try dispel
3694 if (roll_chance_i(miss_chance))
3695 fail_list.push_back(spellInfo->Id);
3696 else
3697 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3699 // Send success log and really remove auras
3700 if (!success_list.empty())
3702 int32 count = success_list.size();
3703 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3704 data.append(unitTarget->GetPackGUID()); // Victim GUID
3705 data.append(m_caster->GetPackGUID()); // Caster GUID
3706 data << uint32(m_spellInfo->Id); // Dispel spell id
3707 data << uint8(0); // not used
3708 data << uint32(count); // count
3709 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3711 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3712 data << uint32(spellInfo->Id); // Spell Id
3713 data << uint8(0); // 0 - dispeled !=0 cleansed
3714 unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3716 m_caster->SendMessageToSet(&data, true);
3718 // On success dispel
3719 // Devour Magic
3720 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3722 int32 heal_amount = m_spellInfo->CalculateSimpleValue(1);
3723 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
3726 // Send fail log to client
3727 if (!fail_list.empty())
3729 // Failed to dispell
3730 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3731 data << uint64(m_caster->GetGUID()); // Caster GUID
3732 data << uint64(unitTarget->GetGUID()); // Victim GUID
3733 data << uint32(m_spellInfo->Id); // Dispell spell id
3734 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3735 data << uint32(*j); // Spell Id
3736 m_caster->SendMessageToSet(&data, true);
3741 void Spell::EffectDualWield(uint32 /*i*/)
3743 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3744 ((Player*)unitTarget)->SetCanDualWield(true);
3747 void Spell::EffectPull(uint32 /*i*/)
3749 // TODO: create a proper pull towards distract spell center for distract
3750 sLog.outDebug("WORLD: Spell Effect DUMMY");
3753 void Spell::EffectDistract(uint32 /*i*/)
3755 // Check for possible target
3756 if (!unitTarget || unitTarget->isInCombat())
3757 return;
3759 // target must be OK to do this
3760 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3761 return;
3763 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3765 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3767 // For players just turn them
3768 WorldPacket data;
3769 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3770 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3771 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3773 else
3775 // Set creature Distracted, Stop it, And turn it
3776 unitTarget->SetOrientation(angle);
3777 unitTarget->StopMoving();
3778 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
3782 void Spell::EffectPickPocket(uint32 /*i*/)
3784 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3785 return;
3787 // victim must be creature and attackable
3788 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
3789 return;
3791 // victim have to be alive and humanoid or undead
3792 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3794 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3796 if (chance > irand(0, 19))
3798 // Stealing successful
3799 //sLog.outDebug("Sending loot from pickpocket");
3800 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3802 else
3804 // Reveal action + get attack
3805 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3806 if (((Creature*)unitTarget)->AI())
3807 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3812 void Spell::EffectAddFarsight(uint32 i)
3814 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3815 return;
3817 int32 duration = GetSpellDuration(m_spellInfo);
3818 DynamicObject* dynObj = new DynamicObject;
3820 // set radius to 0: spell not expected to work as persistent aura
3821 if(!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
3823 delete dynObj;
3824 return;
3826 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3827 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3828 m_caster->AddDynObject(dynObj);
3829 m_caster->GetMap()->Add(dynObj);
3830 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3833 void Spell::EffectSummonWild(uint32 i, uint32 forceFaction)
3835 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3836 if (!creature_entry)
3837 return;
3839 uint32 level = m_caster->getLevel();
3841 // level of creature summoned using engineering item based at engineering skill level
3842 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3844 ItemPrototype const *proto = m_CastItem->GetProto();
3845 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3847 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3848 if (skill202)
3849 level = skill202/5;
3853 // select center of summon position
3854 float center_x = m_targets.m_destX;
3855 float center_y = m_targets.m_destY;
3856 float center_z = m_targets.m_destZ;
3858 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3859 int32 duration = GetSpellDuration(m_spellInfo);
3860 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3862 int32 amount = damage > 0 ? damage : 1;
3864 for(int32 count = 0; count < amount; ++count)
3866 float px, py, pz;
3867 // If dest location if present
3868 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3870 // Summon 1 unit in dest location
3871 if (count == 0)
3873 px = m_targets.m_destX;
3874 py = m_targets.m_destY;
3875 pz = m_targets.m_destZ;
3877 // Summon in random point all other units if location present
3878 else
3879 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3881 // Summon if dest location not present near caster
3882 else
3883 m_caster->GetClosePoint(px, py, pz, 3.0f);
3885 if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
3887 summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3888 summon->SetCreatorGUID(m_caster->GetGUID());
3890 if(forceFaction)
3891 summon->setFaction(forceFaction);
3896 void Spell::EffectSummonGuardian(uint32 i, uint32 forceFaction)
3898 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3899 if (!pet_entry)
3900 return;
3902 // in another case summon new
3903 uint32 level = m_caster->getLevel();
3905 // level of pet summoned using engineering item based at engineering skill level
3906 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
3908 ItemPrototype const *proto = m_CastItem->GetProto();
3909 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3911 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3912 if (skill202)
3914 level = skill202 / 5;
3919 // select center of summon position
3920 float center_x = m_targets.m_destX;
3921 float center_y = m_targets.m_destY;
3922 float center_z = m_targets.m_destZ;
3924 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3925 int32 duration = GetSpellDuration(m_spellInfo);
3926 if(Player* modOwner = m_caster->GetSpellModOwner())
3927 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3929 int32 amount = damage > 0 ? damage : 1;
3931 for(int32 count = 0; count < amount; ++count)
3933 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3935 Map *map = m_caster->GetMap();
3936 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3937 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3938 m_spellInfo->EffectMiscValue[i], pet_number))
3940 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[i]);
3941 delete spawnCreature;
3942 return;
3945 float px, py, pz;
3946 // If dest location if present
3947 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3949 // Summon 1 unit in dest location
3950 if (count == 0)
3952 px = m_targets.m_destX;
3953 py = m_targets.m_destY;
3954 pz = m_targets.m_destZ;
3956 // Summon in random point all other units if location present
3957 else
3958 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3960 // Summon if dest location not present near caster
3961 else
3962 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
3964 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
3966 if (!spawnCreature->IsPositionValid())
3968 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3969 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3970 delete spawnCreature;
3971 return;
3974 if (duration > 0)
3975 spawnCreature->SetDuration(duration);
3977 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3978 spawnCreature->setPowerType(POWER_MANA);
3979 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
3980 spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
3981 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3982 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3983 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3984 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3985 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3987 spawnCreature->InitStatsForLevel(level, m_caster);
3988 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3990 spawnCreature->AIM_Initialize();
3992 m_caster->AddGuardian(spawnCreature);
3994 map->Add((Creature*)spawnCreature);
3998 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
4000 if (!unitTarget)
4001 return;
4003 if (unitTarget->isInFlight())
4004 return;
4006 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
4008 float fx, fy, fz;
4009 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
4011 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
4014 void Spell::EffectLearnSkill(uint32 i)
4016 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4017 return;
4019 if (damage < 0)
4020 return;
4022 uint32 skillid = m_spellInfo->EffectMiscValue[i];
4023 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
4024 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4027 void Spell::EffectAddHonor(uint32 /*i*/)
4029 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4030 return;
4032 // not scale value for item based reward (/10 value expected)
4033 if (m_CastItem)
4035 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage / 10);
4036 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());
4037 return;
4040 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4041 if (damage <= 50)
4043 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
4044 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
4045 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
4047 else
4049 //maybe we have correct honor_gain in damage already
4050 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
4051 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
4055 void Spell::EffectTradeSkill(uint32 /*i*/)
4057 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4058 return;
4059 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4060 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4061 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4064 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
4066 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4067 return;
4068 if (!itemTarget)
4069 return;
4071 Player* p_caster = (Player*)m_caster;
4073 // not grow at item use at item case
4074 p_caster->UpdateCraftSkill(m_spellInfo->Id);
4076 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
4077 if (!enchant_id)
4078 return;
4080 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4081 if (!pEnchant)
4082 return;
4084 // item can be in trade slot and have owner diff. from caster
4085 Player* item_owner = itemTarget->GetOwner();
4086 if (!item_owner)
4087 return;
4089 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4091 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4092 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4093 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4094 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4097 // remove old enchanting before applying new if equipped
4098 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
4100 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4102 // add new enchanting if equipped
4103 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
4106 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
4108 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4109 return;
4110 if (!itemTarget)
4111 return;
4113 Player* p_caster = (Player*)m_caster;
4115 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
4116 if (!enchant_id)
4117 return;
4119 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4120 if (!pEnchant)
4121 return;
4123 // support only enchantings with add socket in this slot
4125 bool add_socket = false;
4126 for(int i = 0; i < 3; ++i)
4128 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
4130 add_socket = true;
4131 break;
4134 if (!add_socket)
4136 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.",
4137 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
4138 return;
4142 // item can be in trade slot and have owner diff. from caster
4143 Player* item_owner = itemTarget->GetOwner();
4144 if (!item_owner)
4145 return;
4147 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4149 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4150 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4151 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4152 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4155 // remove old enchanting before applying new if equipped
4156 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4158 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4160 // add new enchanting if equipped
4161 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4164 void Spell::EffectEnchantItemTmp(uint32 i)
4166 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4167 return;
4169 Player* p_caster = (Player*)m_caster;
4171 // Rockbiter Weapon apply to both weapon
4172 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000))
4174 uint32 spell_id = 0;
4176 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4177 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4178 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4179 switch(damage)
4181 // Rank 1
4182 case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4183 // Rank 2
4184 case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
4185 case 5: spell_id = 36751; break; // 20%
4186 // Rank 3
4187 case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
4188 case 7: spell_id = 36755; break; // 20%
4189 // Rank 4
4190 case 9: spell_id = 36761; break; // 0% [ 7% == 6]
4191 case 10: spell_id = 36758; break; // 14%
4192 case 11: spell_id = 36760; break; // 20%
4193 default:
4194 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
4195 return;
4199 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
4200 if (!spellInfo)
4202 sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
4203 return;
4206 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
4208 if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
4210 if (item->IsFitToSpellRequirements(m_spellInfo))
4212 Spell *spell = new Spell(m_caster, spellInfo, true);
4213 SpellCastTargets targets;
4214 targets.setItemTarget( item );
4215 spell->prepare(&targets);
4219 return;
4222 if (!itemTarget)
4223 return;
4225 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
4227 if (!enchant_id)
4229 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
4230 return;
4233 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4234 if(!pEnchant)
4236 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
4237 return;
4240 // select enchantment duration
4241 uint32 duration;
4243 // rogue family enchantments exception by duration
4244 if(m_spellInfo->Id == 38615)
4245 duration = 1800; // 30 mins
4246 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4247 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4248 duration = 3600; // 1 hour
4249 // shaman family enchantments
4250 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4251 duration = 1800; // 30 mins
4252 // other cases with this SpellVisual already selected
4253 else if(m_spellInfo->SpellVisual[0] == 215)
4254 duration = 1800; // 30 mins
4255 // some fishing pole bonuses
4256 else if(m_spellInfo->SpellVisual[0] == 563)
4257 duration = 600; // 10 mins
4258 // shaman rockbiter enchantments
4259 else if(m_spellInfo->SpellVisual[0] == 0)
4260 duration = 1800; // 30 mins
4261 else if(m_spellInfo->Id == 29702)
4262 duration = 300; // 5 mins
4263 else if(m_spellInfo->Id == 37360)
4264 duration = 300; // 5 mins
4265 // default case
4266 else
4267 duration = 3600; // 1 hour
4269 // item can be in trade slot and have owner diff. from caster
4270 Player* item_owner = itemTarget->GetOwner();
4271 if(!item_owner)
4272 return;
4274 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4276 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4277 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4278 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4279 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4282 // remove old enchanting before applying new if equipped
4283 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4285 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4287 // add new enchanting if equipped
4288 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4291 void Spell::EffectTameCreature(uint32 /*i*/)
4293 // Caster must be player, checked in Spell::CheckCast
4294 // Spell can be triggered, we need to check original caster prior to caster
4295 Player* plr = (Player*)(m_originalCaster ? m_originalCaster : m_caster);
4297 Creature* creatureTarget = (Creature*)unitTarget;
4299 // cast finish successfully
4300 //SendChannelUpdate(0);
4301 finish();
4303 Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4304 if(!pet) // in versy specific state like near world end/etc.
4305 return;
4307 // "kill" original creature
4308 creatureTarget->ForcedDespawn();
4310 uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel();
4312 // prepare visual effect for levelup
4313 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4315 // add to world
4316 pet->GetMap()->Add((Creature*)pet);
4318 // visual effect for levelup
4319 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4321 // caster have pet now
4322 plr->SetPet(pet);
4324 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4325 plr->PetSpellInitialize();
4328 void Spell::EffectSummonPet(uint32 i)
4330 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4332 Pet *OldSummon = m_caster->GetPet();
4334 // if pet requested type already exist
4335 if( OldSummon )
4337 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4339 // pet in corpse state can't be summoned
4340 if( OldSummon->isDead() )
4341 return;
4343 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4345 float px, py, pz;
4346 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4348 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4349 m_caster->GetMap()->Add((Creature*)OldSummon);
4351 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4353 ((Player*)m_caster)->PetSpellInitialize();
4355 return;
4358 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4359 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4360 else
4361 return;
4364 Pet* NewSummon = new Pet;
4366 // petentry==0 for hunter "call pet" (current pet summoned if any)
4367 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4369 if(NewSummon->getPetType()==SUMMON_PET)
4371 // Remove Demonic Sacrifice auras (known pet)
4372 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4373 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4375 if((*itr)->GetModifier()->m_miscvalue == 2228)
4377 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4378 itr = auraClassScripts.begin();
4380 else
4381 ++itr;
4385 return;
4388 // not error in case fail hunter call pet
4389 if(!petentry)
4391 delete NewSummon;
4392 return;
4395 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4397 if(!cInfo)
4399 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4400 delete NewSummon;
4401 return;
4404 Map *map = m_caster->GetMap();
4405 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4406 if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4407 petentry, pet_number))
4409 delete NewSummon;
4410 return;
4413 float px, py, pz;
4414 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4416 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4418 if(!NewSummon->IsPositionValid())
4420 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4421 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4422 delete NewSummon;
4423 return;
4426 uint32 petlevel = m_caster->getLevel();
4427 NewSummon->setPetType(SUMMON_PET);
4429 uint32 faction = m_caster->getFaction();
4430 if(m_caster->GetTypeId() == TYPEID_UNIT)
4432 if ( ((Creature*)m_caster)->isTotem() )
4433 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4434 else
4435 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4438 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4439 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4440 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4441 NewSummon->setFaction(faction);
4442 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4443 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4444 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4445 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4446 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4447 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4449 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4450 // this enables pet details window (Shift+P)
4452 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4453 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4454 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4456 if(m_caster->IsPvP())
4457 NewSummon->SetPvP(true);
4459 NewSummon->InitStatsForLevel(petlevel, m_caster);
4460 NewSummon->InitPetCreateSpells();
4461 NewSummon->InitLevelupSpellsForLevel();
4462 NewSummon->InitTalentForLevel();
4464 if(NewSummon->getPetType()==SUMMON_PET)
4466 // Remove Demonic Sacrifice auras (new pet)
4467 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4468 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4470 if((*itr)->GetModifier()->m_miscvalue==2228)
4472 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4473 itr = auraClassScripts.begin();
4475 else
4476 ++itr;
4479 // generate new name for summon pet
4480 std::string new_name=sObjectMgr.GeneratePetName(petentry);
4481 if(!new_name.empty())
4482 NewSummon->SetName(new_name);
4484 else if(NewSummon->getPetType()==HUNTER_PET)
4485 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4487 NewSummon->AIM_Initialize();
4488 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4489 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4491 map->Add((Creature*)NewSummon);
4493 m_caster->SetPet(NewSummon);
4494 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4496 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4498 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4499 ((Player*)m_caster)->PetSpellInitialize();
4503 void Spell::EffectLearnPetSpell(uint32 i)
4505 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4506 return;
4508 Player *_player = (Player*)m_caster;
4510 Pet *pet = _player->GetPet();
4511 if(!pet)
4512 return;
4513 if(!pet->isAlive())
4514 return;
4516 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4517 if(!learn_spellproto)
4518 return;
4520 pet->learnSpell(learn_spellproto->Id);
4522 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4523 _player->PetSpellInitialize();
4526 void Spell::EffectTaunt(uint32 /*i*/)
4528 if (!unitTarget)
4529 return;
4531 // this effect use before aura Taunt apply for prevent taunt already attacking target
4532 // for spell as marked "non effective at already attacking target"
4533 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4535 if (unitTarget->getVictim()==m_caster)
4537 SendCastResult(SPELL_FAILED_DONT_REPORT);
4538 return;
4542 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4543 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4544 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4547 void Spell::EffectWeaponDmg(uint32 i)
4549 if(!unitTarget)
4550 return;
4551 if(!unitTarget->isAlive())
4552 return;
4554 // multiple weapon dmg effect workaround
4555 // execute only the last weapon damage
4556 // and handle all effects at once
4557 for (int j = 0; j < 3; ++j)
4559 switch(m_spellInfo->Effect[j])
4561 case SPELL_EFFECT_WEAPON_DAMAGE:
4562 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4563 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4564 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4565 if (j < i) // we must calculate only at last weapon effect
4566 return;
4567 break;
4571 // some spell specific modifiers
4572 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4574 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4575 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4576 bool normalized = false;
4578 int32 spell_bonus = 0; // bonus specific for spell
4579 switch(m_spellInfo->SpellFamilyName)
4581 case SPELLFAMILY_WARRIOR:
4583 // Devastate bonus and sunder armor refresh
4584 if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4586 uint32 stack = 0;
4587 // Need refresh all Sunder Armor auras from this caster
4588 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4589 SpellEntry const *spellInfo;
4590 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4592 spellInfo = (*itr).second->GetSpellProto();
4593 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4594 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4595 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4597 (*itr).second->RefreshAura();
4598 stack = (*itr).second->GetStackAmount();
4599 break;
4602 if (stack)
4603 spell_bonus += stack * CalculateDamage(2, unitTarget);
4604 if (!stack || stack < spellInfo->StackAmount)
4605 // Devastate causing Sunder Armor Effect
4606 // and no need to cast over max stack amount
4607 m_caster->CastSpell(unitTarget, 58567, true);
4609 break;
4611 case SPELLFAMILY_ROGUE:
4613 // Mutilate (for each hand)
4614 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4616 bool found = false;
4617 // fast check
4618 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4619 found = true;
4620 // full aura scan
4621 else
4623 Unit::AuraMap const& auras = unitTarget->GetAuras();
4624 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4626 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4628 found = true;
4629 break;
4634 if(found)
4635 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4637 // Fan of Knives
4638 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4640 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
4641 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4642 totalDamagePercentMod *= 1.5f; // 150% to daggers
4644 break;
4646 case SPELLFAMILY_PALADIN:
4648 // Seal of Command - receive benefit from Spell Damage and Healing
4649 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000002000000))
4651 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4652 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4653 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4655 break;
4657 case SPELLFAMILY_SHAMAN:
4659 // Skyshatter Harness item set bonus
4660 // Stormstrike
4661 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4663 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4664 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4666 // Stormstrike AP Buff
4667 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4669 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4670 break;
4674 break;
4676 case SPELLFAMILY_DEATHKNIGHT:
4678 // Blood Strike, Heart Strike, Obliterate
4679 // Blood-Caked Strike, Scourge Strike
4680 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
4681 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
4683 uint32 count = 0;
4684 Unit::AuraMap const& auras = unitTarget->GetAuras();
4685 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4687 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
4688 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
4689 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
4690 ++count;
4693 if (count)
4695 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4696 float bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? 0 : 2, unitTarget) / 100.0f;
4697 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4698 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
4699 m_spellInfo->SpellIconID == 1736)
4700 bonus /= 2.0f;
4702 totalDamagePercentMod *= 1.0f + bonus;
4705 // Glyph of Blood Strike
4706 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000) &&
4707 m_caster->HasAura(59332) &&
4708 unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
4710 totalDamagePercentMod *= 1.2f; // 120% if snared
4712 // Glyph of Death Strike
4713 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010) &&
4714 m_caster->HasAura(59336))
4716 int32 rp = m_caster->GetPower(POWER_RUNIC_POWER) / 10;
4717 if(rp > 25)
4718 rp = 25;
4719 totalDamagePercentMod *= 1.0f + rp / 100.0f;
4721 // Glyph of Plague Strike
4722 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001) &&
4723 m_caster->HasAura(58657) )
4725 totalDamagePercentMod *= 1.2f;
4727 break;
4731 int32 fixed_bonus = 0;
4732 for (int j = 0; j < 3; ++j)
4734 switch(m_spellInfo->Effect[j])
4736 case SPELL_EFFECT_WEAPON_DAMAGE:
4737 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4738 fixed_bonus += CalculateDamage(j, unitTarget);
4739 break;
4740 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4741 fixed_bonus += CalculateDamage(j, unitTarget);
4742 normalized = true;
4743 break;
4744 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4745 weaponDamagePercentMod *= float(CalculateDamage(j, unitTarget)) / 100.0f;
4747 // applied only to prev.effects fixed damage
4748 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4749 break;
4750 default:
4751 break; // not weapon damage effect, just skip
4755 // apply weaponDamagePercentMod to spell bonus also
4756 if(spellBonusNeedWeaponDamagePercentMod)
4757 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4759 // non-weapon damage
4760 int32 bonus = spell_bonus + fixed_bonus;
4762 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4763 if(bonus)
4765 UnitMods unitMod;
4766 switch(m_attackType)
4768 default:
4769 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4770 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4771 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4774 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4775 bonus = int32(bonus*weapon_total_pct);
4778 // + weapon damage with applied weapon% dmg to base weapon damage in call
4779 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4781 // total damage
4782 bonus = int32(bonus*totalDamagePercentMod);
4784 // prevent negative damage
4785 m_damage+= uint32(bonus > 0 ? bonus : 0);
4787 // Hemorrhage
4788 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
4790 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4791 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4793 // Mangle (Cat): CP
4794 else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
4796 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4797 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4799 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_PALADIN)
4801 // Judgement of Blood/of the Martyr backlash damage (33%)
4802 if(m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL && m_spellInfo->SpellIconID==153)
4804 int32 damagePoint = m_damage * 33 / 100;
4805 if(m_spellInfo->Id == 31898)
4806 m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
4807 else
4808 m_caster->CastCustomSpell(m_caster, 53725, &damagePoint, NULL, NULL, true);
4812 // take ammo
4813 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4815 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
4817 // wands don't have ammo
4818 if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
4819 return;
4821 if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
4823 if(pItem->GetMaxStackCount()==1)
4825 // decrease durability for non-stackable throw weapon
4826 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4828 else
4830 // decrease items amount for stackable throw weapon
4831 uint32 count = 1;
4832 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4835 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4836 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4840 void Spell::EffectThreat(uint32 /*i*/)
4842 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4843 return;
4845 if(!unitTarget->CanHaveThreatList())
4846 return;
4848 unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
4851 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4853 if(!unitTarget)
4854 return;
4855 if(!unitTarget->isAlive())
4856 return;
4858 uint32 heal = m_caster->GetMaxHealth();
4860 m_healing += heal;
4863 void Spell::EffectInterruptCast(uint32 /*i*/)
4865 if(!unitTarget)
4866 return;
4867 if(!unitTarget->isAlive())
4868 return;
4870 // TODO: not all spells that used this effect apply cooldown at school spells
4871 // also exist case: apply cooldown to interrupted cast only and to all spells
4872 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
4874 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
4876 SpellEntry const* curSpellInfo = spell->m_spellInfo;
4877 // check if we can interrupt spell
4878 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4880 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
4881 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
4887 void Spell::EffectSummonObjectWild(uint32 i)
4889 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4891 GameObject* pGameObj = new GameObject;
4893 WorldObject* target = focusObject;
4894 if( !target )
4895 target = m_caster;
4897 float x, y, z;
4898 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4900 x = m_targets.m_destX;
4901 y = m_targets.m_destY;
4902 z = m_targets.m_destZ;
4904 else
4905 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4907 Map *map = target->GetMap();
4909 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4910 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4912 delete pGameObj;
4913 return;
4916 int32 duration = GetSpellDuration(m_spellInfo);
4918 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4919 pGameObj->SetSpellId(m_spellInfo->Id);
4921 // Wild object not have owner and check clickable by players
4922 map->Add(pGameObj);
4924 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
4926 Player *pl = (Player*)m_caster;
4927 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4929 switch(pGameObj->GetMapId())
4931 case 489: //WS
4933 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4935 uint32 team = ALLIANCE;
4937 if(pl->GetTeam() == team)
4938 team = HORDE;
4940 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4942 break;
4944 case 566: //EY
4946 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4948 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4950 break;
4955 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
4957 GameObject* linkedGO = new GameObject;
4958 if(linkedGO->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4959 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4961 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4962 linkedGO->SetSpellId(m_spellInfo->Id);
4964 // Wild object not have owner and check clickable by players
4965 map->Add(linkedGO);
4967 else
4969 delete linkedGO;
4970 linkedGO = NULL;
4971 return;
4976 void Spell::EffectScriptEffect(uint32 effIndex)
4978 // TODO: we must implement hunter pet summon at login there (spell 6962)
4980 switch(m_spellInfo->SpellFamilyName)
4982 case SPELLFAMILY_GENERIC:
4984 switch(m_spellInfo->Id)
4986 // PX-238 Winter Wondervolt TRAP
4987 case 26275:
4989 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4991 // check presence
4992 for(int j = 0; j < 4; ++j)
4993 if(unitTarget->HasAura(spells[j],0))
4994 return;
4996 // select spell
4997 uint32 iTmpSpellId = spells[urand(0,3)];
4999 // cast
5000 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
5001 return;
5003 // Bending Shinbone
5004 case 8856:
5006 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
5007 return;
5009 uint32 spell_id = 0;
5010 switch(urand(1, 5))
5012 case 1: spell_id = 8854; break;
5013 default: spell_id = 8855; break;
5016 m_caster->CastSpell(m_caster,spell_id,true,NULL);
5017 return;
5019 // Brittle Armor - need remove one 24575 Brittle Armor aura
5020 case 24590:
5021 unitTarget->RemoveSingleSpellAurasFromStack(24575);
5022 return;
5023 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5024 case 26465:
5025 unitTarget->RemoveSingleSpellAurasFromStack(26464);
5026 return;
5027 // Orb teleport spells
5028 case 25140:
5029 case 25143:
5030 case 25650:
5031 case 25652:
5032 case 29128:
5033 case 29129:
5034 case 35376:
5035 case 35727:
5037 if(!unitTarget)
5038 return;
5040 uint32 spellid;
5041 switch(m_spellInfo->Id)
5043 case 25140: spellid = 32571; break;
5044 case 25143: spellid = 32572; break;
5045 case 25650: spellid = 30140; break;
5046 case 25652: spellid = 30141; break;
5047 case 29128: spellid = 32568; break;
5048 case 29129: spellid = 32569; break;
5049 case 35376: spellid = 25649; break;
5050 case 35727: spellid = 35730; break;
5051 default:
5052 return;
5055 unitTarget->CastSpell(unitTarget,spellid,false);
5056 return;
5058 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
5059 case 22539:
5060 case 22972:
5061 case 22975:
5062 case 22976:
5063 case 22977:
5064 case 22978:
5065 case 22979:
5066 case 22980:
5067 case 22981:
5068 case 22982:
5069 case 22983:
5070 case 22984:
5071 case 22985:
5073 if(!unitTarget || !unitTarget->isAlive())
5074 return;
5076 // Onyxia Scale Cloak
5077 if(unitTarget->GetDummyAura(22683))
5078 return;
5080 // Shadow Flame
5081 m_caster->CastSpell(unitTarget, 22682, true);
5082 return;
5084 // Summon Black Qiraji Battle Tank
5085 case 26656:
5087 if(!unitTarget)
5088 return;
5090 // Prevent stacking of mounts
5091 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5093 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5094 if (unitTarget->GetAreaId() == 3428)
5095 unitTarget->CastSpell(unitTarget, 25863, false);
5096 else
5097 unitTarget->CastSpell(unitTarget, 26655, false);
5098 return;
5100 // Piccolo of the Flaming Fire
5101 case 17512:
5103 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5104 return;
5105 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
5106 return;
5108 // Demonic Empowerment (succubus Vanish effect)
5109 case 54436:
5111 if(!unitTarget)
5112 return;
5114 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5115 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5116 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
5117 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
5118 return;
5120 // Escape artist
5121 case 20589:
5123 if(!unitTarget)
5124 return;
5126 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5127 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5128 return;
5130 // Mirren's Drinking Hat
5131 case 29830:
5133 uint32 item = 0;
5134 switch ( urand(1, 6) )
5136 case 1:
5137 case 2:
5138 case 3:
5139 item = 23584; break; // Loch Modan Lager
5140 case 4:
5141 case 5:
5142 item = 23585; break; // Stouthammer Lite
5143 case 6:
5144 item = 23586; break; // Aerie Peak Pale Ale
5146 if (item)
5147 DoCreateItem(effIndex,item);
5148 break;
5150 // Improved Sprint
5151 case 30918:
5153 if(!unitTarget)
5154 return;
5155 // Removes snares and roots.
5156 unitTarget->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,30918,true);
5157 break;
5159 // Flame Crash
5160 case 41126:
5162 if(!unitTarget)
5163 return;
5165 unitTarget->CastSpell(unitTarget, 41131, true);
5166 break;
5168 // Force Cast - Portal Effect: Sunwell Isle
5169 case 44876:
5171 if(!unitTarget)
5172 return;
5174 unitTarget->CastSpell(unitTarget, 44870, true);
5175 break;
5177 // Goblin Weather Machine
5178 case 46203:
5180 if(!unitTarget)
5181 return;
5183 uint32 spellId = 0;
5184 switch(rand() % 4)
5186 case 0: spellId = 46740; break;
5187 case 1: spellId = 46739; break;
5188 case 2: spellId = 46738; break;
5189 case 3: spellId = 46736; break;
5191 unitTarget->CastSpell(unitTarget, spellId, true);
5192 break;
5194 //5,000 Gold
5195 case 46642:
5197 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5198 return;
5200 ((Player*)unitTarget)->ModifyMoney(50000000);
5202 break;
5204 // Emblazon Runeblade
5205 case 51770:
5207 if(!m_originalCaster)
5208 return;
5210 m_originalCaster->CastSpell(m_originalCaster, damage, false);
5211 break;
5213 // Death Gate
5214 case 52751:
5216 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5217 return;
5218 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5219 unitTarget->CastSpell(unitTarget, damage, false);
5220 break;
5222 // Winged Steed of the Ebon Blade
5223 case 54729:
5225 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5226 return;
5228 // Prevent stacking of mounts
5229 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5231 // Triggered spell id dependent of riding skill
5232 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5234 if (skillval >= 300)
5235 unitTarget->CastSpell(unitTarget, 54727, true);
5236 else
5237 unitTarget->CastSpell(unitTarget, 54726, true);
5239 return;
5241 case 55693: // Remove Collapsing Cave Aura
5242 if(!unitTarget)
5243 return;
5244 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex));
5245 break;
5246 case 58418: // Portal to Orgrimmar
5247 case 58420: // Portal to Stormwind
5249 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
5250 return;
5252 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
5253 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
5255 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5256 unitTarget->CastSpell(unitTarget, spellID, true);
5258 return;
5260 case 59317: // Teleporting
5261 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5262 return;
5264 // return from top
5265 if (((Player*)unitTarget)->GetAreaId() == 4637)
5266 unitTarget->CastSpell(unitTarget, 59316, true);
5267 // teleport atop
5268 else
5269 unitTarget->CastSpell(unitTarget, 59314, true);
5271 return;
5272 // random spell learn instead placeholder
5273 case 60893: // Northrend Alchemy Research
5274 case 61177: // Northrend Inscription Research
5275 case 61288: // Minor Inscription Research
5276 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5277 case 64323: // Book of Glyph Mastery
5279 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5280 return;
5282 // learn random explicit discovery recipe (if any)
5283 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5284 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5285 return;
5288 break;
5290 case SPELLFAMILY_WARLOCK:
5292 switch(m_spellInfo->Id)
5294 // Healthstone creating spells
5295 case 6201:
5296 case 6202:
5297 case 5699:
5298 case 11729:
5299 case 11730:
5300 case 27230:
5301 case 47871:
5302 case 47878:
5304 if(!unitTarget)
5305 return;
5306 uint32 itemtype;
5307 uint32 rank = 0;
5308 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5309 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5311 if((*i)->GetId() == 18692)
5313 rank = 1;
5314 break;
5316 else if((*i)->GetId() == 18693)
5318 rank = 2;
5319 break;
5323 static uint32 const itypes[8][3] = {
5324 { 5512, 19004, 19005}, // Minor Healthstone
5325 { 5511, 19006, 19007}, // Lesser Healthstone
5326 { 5509, 19008, 19009}, // Healthstone
5327 { 5510, 19010, 19011}, // Greater Healthstone
5328 { 9421, 19012, 19013}, // Major Healthstone
5329 {22103, 22104, 22105}, // Master Healthstone
5330 {36889, 36890, 36891}, // Demonic Healthstone
5331 {36892, 36893, 36894} // Fel Healthstone
5334 switch(m_spellInfo->Id)
5336 case 6201:
5337 itemtype=itypes[0][rank];break; // Minor Healthstone
5338 case 6202:
5339 itemtype=itypes[1][rank];break; // Lesser Healthstone
5340 case 5699:
5341 itemtype=itypes[2][rank];break; // Healthstone
5342 case 11729:
5343 itemtype=itypes[3][rank];break; // Greater Healthstone
5344 case 11730:
5345 itemtype=itypes[4][rank];break; // Major Healthstone
5346 case 27230:
5347 itemtype=itypes[5][rank];break; // Master Healthstone
5348 case 47871:
5349 itemtype=itypes[6][rank];break; // Demonic Healthstone
5350 case 47878:
5351 itemtype=itypes[7][rank];break; // Fel Healthstone
5352 default:
5353 return;
5355 DoCreateItem( effIndex, itemtype );
5356 return;
5358 // Demonic Empowerment
5359 case 47193:
5361 if(!unitTarget)
5362 return;
5363 uint32 entry = unitTarget->GetEntry();
5364 uint32 spellID;
5365 switch(entry)
5367 case 416: spellID = 54444; break; //imp
5368 case 417: spellID = 54509; break; //fellhunter
5369 case 1860: spellID = 54443; break; //void
5370 case 1863: spellID = 54435; break; //succubus
5371 case 17252: spellID = 54508; break; //fellguard
5372 default:
5373 return;
5375 unitTarget->CastSpell(unitTarget,spellID,true);
5376 return;
5378 // Everlasting Affliction
5379 case 47422:
5381 // Need refresh caster corruption auras on target
5382 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5383 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5385 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5386 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5387 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5388 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5389 (*itr).second->RefreshAura();
5391 return;
5393 // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5394 case 63521:
5396 // Divine Plea, refresh on target (3 aura slots)
5397 if (Aura* aura = unitTarget->GetAura(54428,0))
5398 aura->RefreshAura();
5399 return;
5402 break;
5404 case SPELLFAMILY_PRIEST:
5406 switch(m_spellInfo->Id)
5408 // Pain and Suffering
5409 case 47948:
5411 if (!unitTarget)
5412 return;
5413 // Refresh Shadow Word: Pain on target
5414 Unit::AuraMap& auras = unitTarget->GetAuras();
5415 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5417 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5418 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5419 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5420 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5422 (*itr).second->RefreshAura();
5423 return;
5426 return;
5428 default:
5429 break;
5431 break;
5433 case SPELLFAMILY_HUNTER:
5435 switch(m_spellInfo->Id)
5437 // Chimera Shot
5438 case 53209:
5440 if(!unitTarget)
5441 return;
5442 uint32 spellId = 0;
5443 int32 basePoint = 0;
5444 Unit* target = unitTarget;
5445 Unit::AuraMap& Auras = unitTarget->GetAuras();
5446 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5448 Aura *aura = (*i).second;
5449 if (aura->GetCasterGUID() != m_caster->GetGUID())
5450 continue;
5451 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5452 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5453 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5454 continue;
5455 // Refresh aura duration
5456 aura->RefreshAura();
5458 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5459 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == 0)
5461 // m_amount already include RAP bonus
5462 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5463 spellId = 53353; // Chimera Shot - Serpent
5465 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5466 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == 0)
5468 uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
5469 if (!target_max_mana)
5470 continue;
5472 // ignore non positive values (can be result apply spellmods to aura damage
5473 uint32 pdamage = aura->GetModifier()->m_amount > 0 ? aura->GetModifier()->m_amount : 0;
5475 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5476 uint32 maxmana = m_caster->GetMaxPower(POWER_MANA) * pdamage * 2 / 100;
5478 pdamage = target_max_mana * pdamage / 100;
5479 if (pdamage > maxmana)
5480 pdamage = maxmana;
5482 pdamage *= 4; // total aura damage
5483 basePoint = pdamage * 60 / 100;
5484 spellId = 53358; // Chimera Shot - Viper
5485 target = m_caster;
5487 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5488 if (familyFlag & UI64LIT(0x0000000000008000))
5489 spellId = 53359; // Chimera Shot - Scorpid
5490 // ?? nothing say in spell desc (possibly need addition check)
5491 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5492 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5494 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5497 if (spellId)
5498 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5499 return;
5501 case 53412: // Invigoration (pet triggered script, master targeted)
5503 if (!unitTarget)
5504 return;
5506 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5507 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5509 // Invigoration (master talent)
5510 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5512 if (roll_chance_i((*i)->GetModifier()->m_amount))
5514 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5515 break;
5519 return;
5521 // Master's Call
5522 case 53271:
5524 if (!unitTarget)
5525 return;
5527 // script effect have in value, but this outdated removed part
5528 unitTarget->CastSpell(unitTarget, 62305, true);
5529 return;
5531 default:
5532 break;
5534 break;
5536 case SPELLFAMILY_PALADIN:
5538 // Judgement (seal trigger)
5539 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5541 if(!unitTarget || !unitTarget->isAlive())
5542 return;
5543 uint32 spellId1 = 0;
5544 uint32 spellId2 = 0;
5546 // Judgement self add switch
5547 switch (m_spellInfo->Id)
5549 case 53407: spellId1 = 20184; break; // Judgement of Justice
5550 case 20271: // Judgement of Light
5551 case 57774: spellId1 = 20185; break; // Judgement of Light
5552 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5553 default:
5554 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
5555 return;
5557 // offensive seals have aura dummy in 2 effect
5558 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5559 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5561 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
5562 if ((*itr)->GetEffIndex() != 2 || !IsSealSpell((*itr)->GetSpellProto()))
5563 continue;
5564 spellId2 = (*itr)->GetModifier()->m_amount;
5565 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5566 if (!judge)
5567 continue;
5568 break;
5570 // if there were no offensive seals than there is seal with proc trigger aura
5571 if (!spellId2)
5573 Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5574 for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
5576 if ((*itr)->GetEffIndex() != 0 || !IsSealSpell((*itr)->GetSpellProto()))
5577 continue;
5578 spellId2 = 54158;
5579 break;
5582 if (spellId1)
5583 m_caster->CastSpell(unitTarget, spellId1, true);
5584 if (spellId2)
5585 m_caster->CastSpell(unitTarget, spellId2, true);
5586 return;
5589 case SPELLFAMILY_POTION:
5591 switch(m_spellInfo->Id)
5593 // Dreaming Glory
5594 case 28698:
5596 if(!unitTarget)
5597 return;
5598 unitTarget->CastSpell(unitTarget, 28694, true);
5599 break;
5601 // Netherbloom
5602 case 28702:
5604 if(!unitTarget)
5605 return;
5606 // 25% chance of casting a random buff
5607 if(roll_chance_i(75))
5608 return;
5610 // triggered spells are 28703 to 28707
5611 // Note: some sources say, that there was the possibility of
5612 // receiving a debuff. However, this seems to be removed by a patch.
5613 const uint32 spellid = 28703;
5615 // don't overwrite an existing aura
5616 for(uint8 i = 0; i < 5; ++i)
5617 if(unitTarget->HasAura(spellid + i, 0))
5618 return;
5619 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5620 break;
5623 // Nightmare Vine
5624 case 28720:
5626 if(!unitTarget)
5627 return;
5628 // 25% chance of casting Nightmare Pollen
5629 if(roll_chance_i(75))
5630 return;
5631 unitTarget->CastSpell(unitTarget, 28721, true);
5632 break;
5635 break;
5637 case SPELLFAMILY_DEATHKNIGHT:
5639 switch(m_spellInfo->Id)
5641 // Pestilence
5642 case 50842:
5644 if(!unitTarget)
5645 return;
5647 Unit* mainTarget = m_targets.getUnitTarget();
5648 if(!mainTarget)
5649 return;
5651 // do only refresh diseases on main target if caster has Glyph of Disease
5652 if(mainTarget == unitTarget && !m_caster->HasAura(63334))
5653 return;
5655 // Blood Plague
5656 if(mainTarget->HasAura(55078))
5657 m_caster->CastSpell(unitTarget, 55078, true);
5659 // Frost Fever
5660 if(mainTarget->HasAura(55095))
5661 m_caster->CastSpell(unitTarget, 55095, true);
5663 break;
5666 break;
5670 // normal DB scripted effect
5671 if(!unitTarget)
5672 return;
5674 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5675 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5678 void Spell::EffectSanctuary(uint32 /*i*/)
5680 if(!unitTarget)
5681 return;
5682 //unitTarget->CombatStop();
5684 unitTarget->CombatStop();
5685 unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
5686 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5687 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5689 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5693 void Spell::EffectAddComboPoints(uint32 /*i*/)
5695 if(!unitTarget)
5696 return;
5698 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5699 return;
5701 if(damage <= 0)
5702 return;
5704 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5707 void Spell::EffectDuel(uint32 i)
5709 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5710 return;
5712 Player *caster = (Player*)m_caster;
5713 Player *target = (Player*)unitTarget;
5715 // caster or target already have requested duel
5716 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5717 return;
5719 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5720 // Don't have to check the target's map since you cannot challenge someone across maps
5721 uint32 mapid = caster->GetMapId();
5722 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5724 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5725 return;
5728 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5729 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5731 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5732 return;
5735 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5736 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5738 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5739 return;
5742 //CREATE DUEL FLAG OBJECT
5743 GameObject* pGameObj = new GameObject;
5745 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5747 Map *map = m_caster->GetMap();
5748 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5749 map, m_caster->GetPhaseMask(),
5750 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5751 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5752 m_caster->GetPositionZ(),
5753 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5755 delete pGameObj;
5756 return;
5759 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5760 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5761 int32 duration = GetSpellDuration(m_spellInfo);
5762 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5763 pGameObj->SetSpellId(m_spellInfo->Id);
5765 m_caster->AddGameObject(pGameObj);
5766 map->Add(pGameObj);
5767 //END
5769 // Send request
5770 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
5771 data << uint64(pGameObj->GetGUID());
5772 data << uint64(caster->GetGUID());
5773 caster->GetSession()->SendPacket(&data);
5774 target->GetSession()->SendPacket(&data);
5776 // create duel-info
5777 DuelInfo *duel = new DuelInfo;
5778 duel->initiator = caster;
5779 duel->opponent = target;
5780 duel->startTime = 0;
5781 duel->startTimer = 0;
5782 caster->duel = duel;
5784 DuelInfo *duel2 = new DuelInfo;
5785 duel2->initiator = caster;
5786 duel2->opponent = caster;
5787 duel2->startTime = 0;
5788 duel2->startTimer = 0;
5789 target->duel = duel2;
5791 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5792 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5795 void Spell::EffectStuck(uint32 /*i*/)
5797 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5798 return;
5800 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5801 return;
5803 Player* pTarget = (Player*)unitTarget;
5805 sLog.outDebug("Spell Effect: Stuck");
5806 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());
5808 if(pTarget->isInFlight())
5809 return;
5811 // homebind location is loaded always
5812 pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
5814 // Stuck spell trigger Hearthstone cooldown
5815 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5816 if(!spellInfo)
5817 return;
5818 Spell spell(pTarget, spellInfo, true, 0);
5819 spell.SendSpellCooldown();
5822 void Spell::EffectSummonPlayer(uint32 /*i*/)
5824 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5825 return;
5827 // Evil Twin (ignore player summon, but hide this for summoner)
5828 if(unitTarget->GetDummyAura(23445))
5829 return;
5831 float x, y, z;
5832 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
5834 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5836 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5837 data << uint64(m_caster->GetGUID()); // summoner guid
5838 data << uint32(m_caster->GetZoneId()); // summoner zone
5839 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5840 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5843 static ScriptInfo generateActivateCommand()
5845 ScriptInfo si;
5846 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5847 return si;
5850 void Spell::EffectActivateObject(uint32 effect_idx)
5852 if(!gameObjTarget)
5853 return;
5855 static ScriptInfo activateCommand = generateActivateCommand();
5857 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5859 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5862 void Spell::EffectApplyGlyph(uint32 i)
5864 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5865 return;
5867 Player *player = (Player*)m_caster;
5869 // apply new one
5870 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5872 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5874 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5876 if(gp->TypeFlags != gs->TypeFlags)
5878 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5879 return; // glyph slot mismatch
5883 // remove old glyph
5884 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5886 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5888 player->RemoveAurasDueToSpell(old_gp->SpellId);
5889 player->SetGlyph(m_glyphIndex, 0);
5893 player->CastSpell(m_caster, gp->SpellId, true);
5894 player->SetGlyph(m_glyphIndex, glyph);
5895 player->SendTalentsInfoData(false);
5900 void Spell::EffectSummonTotem(uint32 i, uint8 slot)
5902 slot = slot ? (slot - 1): 255;
5904 if(slot < MAX_TOTEM)
5906 uint64 guid = m_caster->m_TotemSlot[slot];
5907 if(guid != 0)
5909 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5910 if(OldTotem && OldTotem->isTotem())
5911 ((Totem*)OldTotem)->UnSummon();
5915 uint32 team = 0;
5916 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5917 team = ((Player*)m_caster)->GetTeam();
5919 Totem* pTotem = new Totem;
5921 if(!pTotem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5922 m_spellInfo->EffectMiscValue[i], team ))
5924 delete pTotem;
5925 return;
5928 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5930 float x, y, z;
5931 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
5933 // totem must be at same Z in case swimming caster and etc.
5934 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5935 z = m_caster->GetPositionZ();
5937 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5939 if(slot < MAX_TOTEM)
5940 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5942 pTotem->SetOwner(m_caster->GetGUID());
5943 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5945 int32 duration=GetSpellDuration(m_spellInfo);
5946 if(Player* modOwner = m_caster->GetSpellModOwner())
5947 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
5948 pTotem->SetDuration(duration);
5950 if (damage) // if not spell info, DB values used
5952 pTotem->SetMaxHealth(damage);
5953 pTotem->SetHealth(damage);
5956 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5958 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5959 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
5961 if(m_caster->IsPvP())
5962 pTotem->SetPvP(true);
5964 pTotem->Summon(m_caster);
5966 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5968 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
5969 data << uint8(slot);
5970 data << uint64(pTotem->GetGUID());
5971 data << uint32(duration);
5972 data << uint32(m_spellInfo->Id);
5973 ((Player*)m_caster)->SendDirectMessage(&data);
5977 void Spell::EffectEnchantHeldItem(uint32 i)
5979 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5980 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5981 return;
5983 Player* item_owner = (Player*)unitTarget;
5984 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5986 if(!item )
5987 return;
5989 // must be equipped
5990 if(!item ->IsEquipped())
5991 return;
5993 if (m_spellInfo->EffectMiscValue[i])
5995 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5996 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5997 if(!duration)
5998 duration = m_currentBasePoints[i]+1; //Base points after ..
5999 if(!duration)
6000 duration = 10; //10 seconds for enchants which don't have listed duration
6002 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6003 if(!pEnchant)
6004 return;
6006 // Always go to temp enchantment slot
6007 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
6009 // Enchantment will not be applied if a different one already exists
6010 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
6011 return;
6013 // Apply the temporary enchantment
6014 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
6015 item_owner->ApplyEnchantment(item, slot, true);
6019 void Spell::EffectDisEnchant(uint32 /*i*/)
6021 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6022 return;
6024 Player* p_caster = (Player*)m_caster;
6025 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
6026 return;
6028 p_caster->UpdateCraftSkill(m_spellInfo->Id);
6030 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
6032 // item will be removed at disenchanting end
6035 void Spell::EffectInebriate(uint32 /*i*/)
6037 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6038 return;
6040 Player *player = (Player*)unitTarget;
6041 uint16 currentDrunk = player->GetDrunkValue();
6042 uint16 drunkMod = damage * 256;
6043 if (currentDrunk + drunkMod > 0xFFFF)
6044 currentDrunk = 0xFFFF;
6045 else
6046 currentDrunk += drunkMod;
6047 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
6050 void Spell::EffectFeedPet(uint32 i)
6052 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6053 return;
6055 Player *_player = (Player*)m_caster;
6057 Item* foodItem = m_targets.getItemTarget();
6058 if(!foodItem)
6059 return;
6061 Pet *pet = _player->GetPet();
6062 if(!pet)
6063 return;
6065 if(!pet->isAlive())
6066 return;
6068 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
6069 if(benefit <= 0)
6070 return;
6072 uint32 count = 1;
6073 _player->DestroyItemCount(foodItem,count,true);
6074 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6076 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[i], &benefit, NULL, NULL, true);
6079 void Spell::EffectDismissPet(uint32 /*i*/)
6081 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6082 return;
6084 Pet* pet = m_caster->GetPet();
6086 // not let dismiss dead pet
6087 if(!pet||!pet->isAlive())
6088 return;
6090 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
6093 void Spell::EffectSummonObject(uint32 i)
6095 uint32 go_id = m_spellInfo->EffectMiscValue[i];
6097 uint8 slot = 0;
6098 switch(m_spellInfo->Effect[i])
6100 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
6101 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
6102 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
6103 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
6104 default: return;
6107 if(uint64 guid = m_caster->m_ObjectSlot[slot])
6109 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
6110 obj->SetLootState(GO_JUST_DEACTIVATED);
6111 m_caster->m_ObjectSlot[slot] = 0;
6114 GameObject* pGameObj = new GameObject;
6116 float x, y, z;
6117 // If dest location if present
6118 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6120 x = m_targets.m_destX;
6121 y = m_targets.m_destY;
6122 z = m_targets.m_destZ;
6124 // Summon in random point all other units if location present
6125 else
6126 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
6128 Map *map = m_caster->GetMap();
6129 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
6130 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6132 delete pGameObj;
6133 return;
6136 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
6137 int32 duration = GetSpellDuration(m_spellInfo);
6138 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6139 pGameObj->SetSpellId(m_spellInfo->Id);
6140 m_caster->AddGameObject(pGameObj);
6142 map->Add(pGameObj);
6144 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
6147 void Spell::EffectResurrect(uint32 /*effIndex*/)
6149 if(!unitTarget)
6150 return;
6151 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6152 return;
6154 if(unitTarget->isAlive())
6155 return;
6156 if(!unitTarget->IsInWorld())
6157 return;
6159 switch (m_spellInfo->Id)
6161 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6162 case 8342:
6163 if (roll_chance_i(67))
6165 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
6166 return;
6168 break;
6169 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6170 case 22999:
6171 if (roll_chance_i(50))
6173 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
6174 return;
6176 break;
6177 default:
6178 break;
6181 Player* pTarget = ((Player*)unitTarget);
6183 if(pTarget->isRessurectRequested()) // already have one active request
6184 return;
6186 uint32 health = pTarget->GetMaxHealth() * damage / 100;
6187 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
6189 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
6190 SendResurrectRequest(pTarget);
6193 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
6195 if(!unitTarget || !unitTarget->isAlive())
6196 return;
6198 if( unitTarget->m_extraAttacks )
6199 return;
6201 unitTarget->m_extraAttacks = damage;
6204 void Spell::EffectParry(uint32 /*i*/)
6206 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6207 ((Player*)unitTarget)->SetCanParry(true);
6210 void Spell::EffectBlock(uint32 /*i*/)
6212 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6213 ((Player*)unitTarget)->SetCanBlock(true);
6216 void Spell::EffectLeapForward(uint32 i)
6218 if(unitTarget->isInFlight())
6219 return;
6221 if( m_spellInfo->rangeIndex == 1) //self range
6223 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6225 // before caster
6226 float fx, fy, fz;
6227 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6228 float ox, oy, oz;
6229 unitTarget->GetPosition(ox, oy, oz);
6231 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6232 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
6234 fx = fx2;
6235 fy = fy2;
6236 fz = fz2;
6237 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6240 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6244 void Spell::EffectLeapBack(uint32 i)
6246 if(unitTarget->isInFlight())
6247 return;
6249 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6252 void Spell::EffectReputation(uint32 i)
6254 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6255 return;
6257 Player *_player = (Player*)unitTarget;
6259 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
6261 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
6263 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6265 if(!factionEntry)
6266 return;
6268 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6271 void Spell::EffectQuestComplete(uint32 i)
6273 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6274 return;
6276 Player *_player = (Player*)m_caster;
6278 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
6279 _player->AreaExploredOrEventHappens(quest_id);
6282 void Spell::EffectSelfResurrect(uint32 i)
6284 if(!unitTarget || unitTarget->isAlive())
6285 return;
6286 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6287 return;
6288 if(!unitTarget->IsInWorld())
6289 return;
6291 uint32 health = 0;
6292 uint32 mana = 0;
6294 // flat case
6295 if(damage < 0)
6297 health = uint32(-damage);
6298 mana = m_spellInfo->EffectMiscValue[i];
6300 // percent case
6301 else
6303 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6304 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6305 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6308 Player *plr = ((Player*)unitTarget);
6309 plr->ResurrectPlayer(0.0f);
6311 plr->SetHealth( health );
6312 plr->SetPower(POWER_MANA, mana );
6313 plr->SetPower(POWER_RAGE, 0 );
6314 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6316 plr->SpawnCorpseBones();
6319 void Spell::EffectSkinning(uint32 /*i*/)
6321 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6322 return;
6323 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6324 return;
6326 Creature* creature = (Creature*) unitTarget;
6327 int32 targetLevel = creature->getLevel();
6329 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6331 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6332 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6334 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6336 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6338 // Double chances for elites
6339 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6342 void Spell::EffectCharge(uint32 /*i*/)
6344 if (!unitTarget)
6345 return;
6347 //TODO: research more ContactPoint/attack distance.
6348 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6349 float x, y, z;
6350 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6352 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6353 ((Creature *)unitTarget)->StopMoving();
6355 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6356 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6358 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6359 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6361 // not all charge effects used in negative spells
6362 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6363 m_caster->Attack(unitTarget,true);
6366 void Spell::EffectCharge2(uint32 /*i*/)
6368 float x, y, z;
6369 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6371 x = m_targets.m_destX;
6372 y = m_targets.m_destY;
6373 z = m_targets.m_destZ;
6375 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6376 ((Creature *)unitTarget)->StopMoving();
6378 else if (unitTarget && unitTarget != m_caster)
6379 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6380 else
6381 return;
6383 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6384 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6386 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6387 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6389 // not all charge effects used in negative spells
6390 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6391 m_caster->Attack(unitTarget,true);
6394 void Spell::EffectSummonCritter(uint32 i, uint32 forceFaction)
6396 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6397 return;
6398 Player* player = (Player*)m_caster;
6400 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
6401 if(!pet_entry)
6402 return;
6404 Pet* old_critter = player->GetMiniPet();
6406 // for same pet just despawn
6407 if(old_critter && old_critter->GetEntry() == pet_entry)
6409 player->RemoveMiniPet();
6410 return;
6413 // despawn old pet before summon new
6414 if(old_critter)
6415 player->RemoveMiniPet();
6417 // summon new pet
6418 Pet* critter = new Pet(MINI_PET);
6420 Map *map = m_caster->GetMap();
6421 uint32 pet_number = sObjectMgr.GeneratePetNumber();
6422 if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6423 pet_entry, pet_number))
6425 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6426 delete critter;
6427 return;
6430 float x, y, z;
6431 // If dest location if present
6432 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6434 x = m_targets.m_destX;
6435 y = m_targets.m_destY;
6436 z = m_targets.m_destZ;
6438 // Summon if dest location not present near caster
6439 else
6440 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6442 critter->Relocate(x, y, z, m_caster->GetOrientation());
6444 if(!critter->IsPositionValid())
6446 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6447 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6448 delete critter;
6449 return;
6452 critter->SetOwnerGUID(m_caster->GetGUID());
6453 critter->SetCreatorGUID(m_caster->GetGUID());
6455 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6456 critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
6457 critter->AIM_Initialize();
6458 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6459 //critter->InitLevelupSpellsForLevel(); // none?
6460 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6461 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6462 // some mini-pets have quests
6464 // set timer for unsummon
6465 int32 duration = GetSpellDuration(m_spellInfo);
6466 if(duration > 0)
6467 critter->SetDuration(duration);
6469 std::string name = player->GetName();
6470 name.append(petTypeSuffix[critter->getPetType()]);
6471 critter->SetName( name );
6472 player->SetMiniPet(critter);
6474 map->Add((Creature*)critter);
6477 void Spell::EffectKnockBack(uint32 i)
6479 if(!unitTarget)
6480 return;
6482 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6485 void Spell::EffectSendTaxi(uint32 i)
6487 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6488 return;
6490 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id);
6493 void Spell::EffectPlayerPull(uint32 i)
6495 if(!unitTarget)
6496 return;
6498 unitTarget->KnockBackFrom(m_caster,float(damage ? damage : unitTarget->GetDistance2d(m_caster)),float(m_spellInfo->EffectMiscValue[i])/10);
6501 void Spell::EffectDispelMechanic(uint32 i)
6503 if(!unitTarget)
6504 return;
6506 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6508 Unit::AuraMap& Auras = unitTarget->GetAuras();
6509 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6511 next = iter;
6512 ++next;
6513 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6514 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6516 unitTarget->RemoveAurasDueToSpell(spell->Id);
6517 if(Auras.empty())
6518 break;
6519 else
6520 next = Auras.begin();
6523 return;
6526 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6528 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6529 return;
6530 Player *_player = (Player*)m_caster;
6531 Pet *pet = _player->GetPet();
6532 if(!pet)
6533 return;
6534 if(pet->isAlive())
6535 return;
6536 if(damage < 0)
6537 return;
6538 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6539 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6540 pet->setDeathState( ALIVE );
6541 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6542 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6544 pet->AIM_Initialize();
6546 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6547 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6550 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6552 int32 mana = 0;
6553 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6555 if(!m_caster->m_TotemSlot[slot])
6556 continue;
6558 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6559 if(totem && totem->isTotem())
6561 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6562 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6563 if(spellInfo)
6565 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6566 mana += manacost * damage / 100;
6568 ((Totem*)totem)->UnSummon();
6572 if (mana)
6573 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
6576 void Spell::EffectDurabilityDamage(uint32 i)
6578 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6579 return;
6581 int32 slot = m_spellInfo->EffectMiscValue[i];
6583 // FIXME: some spells effects have value -1/-2
6584 // Possibly its mean -1 all player equipped items and -2 all items
6585 if(slot < 0)
6587 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
6588 return;
6591 // invalid slot value
6592 if(slot >= INVENTORY_SLOT_BAG_END)
6593 return;
6595 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6596 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
6599 void Spell::EffectDurabilityDamagePCT(uint32 i)
6601 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6602 return;
6604 int32 slot = m_spellInfo->EffectMiscValue[i];
6606 // FIXME: some spells effects have value -1/-2
6607 // Possibly its mean -1 all player equipped items and -2 all items
6608 if(slot < 0)
6610 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
6611 return;
6614 // invalid slot value
6615 if(slot >= INVENTORY_SLOT_BAG_END)
6616 return;
6618 if(damage <= 0)
6619 return;
6621 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6622 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
6625 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6627 if(!unitTarget)
6628 return;
6630 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6633 void Spell::EffectTransmitted(uint32 effIndex)
6635 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6637 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
6639 if (!goinfo)
6641 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6642 return;
6645 float fx, fy, fz;
6647 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6649 fx = m_targets.m_destX;
6650 fy = m_targets.m_destY;
6651 fz = m_targets.m_destZ;
6653 //FIXME: this can be better check for most objects but still hack
6654 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6656 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6657 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6659 else
6661 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6662 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6663 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6665 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6668 Map *cMap = m_caster->GetMap();
6670 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6672 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6673 { // but this is not proper, we really need to ignore not materialized objects
6674 SendCastResult(SPELL_FAILED_NOT_HERE);
6675 SendChannelUpdate(0);
6676 return;
6679 // replace by water level in this case
6680 fz = cMap->GetWaterLevel(fx, fy);
6682 // if gameobject is summoning object, it should be spawned right on caster's position
6683 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6685 m_caster->GetPosition(fx, fy, fz);
6688 GameObject* pGameObj = new GameObject;
6690 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6691 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6693 delete pGameObj;
6694 return;
6697 int32 duration = GetSpellDuration(m_spellInfo);
6699 switch(goinfo->type)
6701 case GAMEOBJECT_TYPE_FISHINGNODE:
6703 m_caster->SetChannelObjectGUID(pGameObj->GetGUID());
6704 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6706 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6707 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6708 int32 lastSec = 0;
6709 switch(urand(0, 3))
6711 case 0: lastSec = 3; break;
6712 case 1: lastSec = 7; break;
6713 case 2: lastSec = 13; break;
6714 case 3: lastSec = 17; break;
6717 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6718 break;
6720 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6722 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6724 pGameObj->AddUniqueUse((Player*)m_caster);
6725 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6727 break;
6729 case GAMEOBJECT_TYPE_FISHINGHOLE:
6730 case GAMEOBJECT_TYPE_CHEST:
6731 default:
6732 break;
6735 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6737 pGameObj->SetOwnerGUID(m_caster->GetGUID());
6739 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6740 pGameObj->SetSpellId(m_spellInfo->Id);
6742 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6743 //m_caster->AddGameObject(pGameObj);
6744 //m_ObjToDel.push_back(pGameObj);
6746 cMap->Add(pGameObj);
6748 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
6750 GameObject* linkedGO = new GameObject;
6751 if(linkedGO->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6752 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6754 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6755 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6756 linkedGO->SetSpellId(m_spellInfo->Id);
6757 linkedGO->SetOwnerGUID(m_caster->GetGUID());
6759 linkedGO->GetMap()->Add(linkedGO);
6761 else
6763 delete linkedGO;
6764 linkedGO = NULL;
6765 return;
6770 void Spell::EffectProspecting(uint32 /*i*/)
6772 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6773 return;
6775 Player* p_caster = (Player*)m_caster;
6776 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6777 return;
6779 if(itemTarget->GetCount() < 5)
6780 return;
6782 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6784 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6785 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6786 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6789 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6792 void Spell::EffectMilling(uint32 /*i*/)
6794 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6795 return;
6797 Player* p_caster = (Player*)m_caster;
6798 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6799 return;
6801 if(itemTarget->GetCount() < 5)
6802 return;
6804 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6806 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6807 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6808 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6811 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6814 void Spell::EffectSkill(uint32 /*i*/)
6816 sLog.outDebug("WORLD: SkillEFFECT");
6819 void Spell::EffectSpiritHeal(uint32 /*i*/)
6821 // TODO player can't see the heal-animation - he should respawn some ticks later
6822 if (!unitTarget || unitTarget->isAlive())
6823 return;
6824 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6825 return;
6826 if (!unitTarget->IsInWorld())
6827 return;
6828 if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584))
6829 return;
6831 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6832 ((Player*)unitTarget)->SpawnCorpseBones();
6835 // remove insignia spell effect
6836 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6838 sLog.outDebug("Effect: SkinPlayerCorpse");
6839 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6840 return;
6842 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6845 void Spell::EffectStealBeneficialBuff(uint32 i)
6847 sLog.outDebug("Effect: StealBeneficialBuff");
6849 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6850 return;
6852 std::vector <Aura *> steal_list;
6853 // Create dispel mask by dispel type
6854 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6855 Unit::AuraMap const& auras = unitTarget->GetAuras();
6856 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6858 Aura *aur = (*itr).second;
6859 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6861 // Need check for passive? this
6862 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6863 steal_list.push_back(aur);
6866 // Ok if exist some buffs for dispel try dispel it
6867 if (!steal_list.empty())
6869 std::list < std::pair<uint32,uint64> > success_list;
6870 int32 list_size = steal_list.size();
6871 // Dispell N = damage buffs (or while exist buffs for dispel)
6872 for (int32 count=0; count < damage && list_size > 0; ++count)
6874 // Random select buff for dispel
6875 Aura *aur = steal_list[urand(0, list_size-1)];
6876 // Not use chance for steal
6877 // TODO possible need do it
6878 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6880 // Remove buff from list for prevent doubles
6881 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6883 Aura *stealed = *j;
6884 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6886 j = steal_list.erase(j);
6887 --list_size;
6889 else
6890 ++j;
6893 // Really try steal and send log
6894 if (!success_list.empty())
6896 int32 count = success_list.size();
6897 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6898 data.append(unitTarget->GetPackGUID()); // Victim GUID
6899 data.append(m_caster->GetPackGUID()); // Caster GUID
6900 data << uint32(m_spellInfo->Id); // Dispell spell id
6901 data << uint8(0); // not used
6902 data << uint32(count); // count
6903 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6905 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6906 data << uint32(spellInfo->Id); // Spell Id
6907 data << uint8(0); // 0 - steals !=0 transfers
6908 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6910 m_caster->SendMessageToSet(&data, true);
6915 void Spell::EffectKillCreditPersonal(uint32 i)
6917 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6918 return;
6920 ((Player*)unitTarget)->KilledMonsterCredit(m_spellInfo->EffectMiscValue[i], 0);
6923 void Spell::EffectKillCredit(uint32 i)
6925 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6926 return;
6928 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6931 void Spell::EffectQuestFail(uint32 i)
6933 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6934 return;
6936 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6939 void Spell::EffectActivateRune(uint32 eff_idx)
6941 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6942 return;
6944 Player *plr = (Player*)m_caster;
6946 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6947 return;
6949 for(uint32 j = 0; j < MAX_RUNES; ++j)
6951 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
6953 plr->SetRuneCooldown(j, 0);
6958 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6960 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6961 ((Player*)unitTarget)->SetCanTitanGrip(true);
6964 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6966 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6967 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6968 return;
6970 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
6973 void Spell::EffectPlayMusic(uint32 i)
6975 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6976 return;
6978 uint32 soundid = m_spellInfo->EffectMiscValue[i];
6980 if (!sSoundEntriesStore.LookupEntry(soundid))
6982 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
6983 return;
6986 WorldPacket data(SMSG_PLAY_MUSIC, 4);
6987 data << uint32(soundid);
6988 ((Player*)unitTarget)->GetSession()->SendPacket(&data);