allow .goname and .namego in more battleground cases
[getmangos.git] / src / game / SpellEffects.cpp
blobe670d525db33b7b591f221e7dae64bd171c4227c
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 "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "UpdateMask.h"
27 #include "World.h"
28 #include "ObjectMgr.h"
29 #include "SpellMgr.h"
30 #include "Player.h"
31 #include "SkillExtraItems.h"
32 #include "Unit.h"
33 #include "CreatureAI.h"
34 #include "Spell.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
37 #include "Group.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
42 #include "Pet.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
45 #include "Creature.h"
46 #include "Totem.h"
47 #include "CreatureAI.h"
48 #include "BattleGroundMgr.h"
49 #include "BattleGround.h"
50 #include "BattleGroundEY.h"
51 #include "BattleGroundWS.h"
52 #include "VMapFactory.h"
53 #include "Language.h"
54 #include "SocialMgr.h"
55 #include "Util.h"
56 #include "TemporarySummon.h"
57 #include "ScriptCalls.h"
58 #include "SkillDiscovery.h"
60 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
62 &Spell::EffectNULL, // 0
63 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
64 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
65 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
66 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
67 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
68 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
69 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
70 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
71 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
72 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
73 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
74 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
75 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
76 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
77 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
78 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
79 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
80 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
81 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
82 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
83 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
84 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
85 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
86 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
87 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
88 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
89 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
90 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
91 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
92 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
93 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
94 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
95 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
96 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
97 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
98 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
99 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
100 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
101 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
102 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
103 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
104 &Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2
105 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
106 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
107 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
108 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
109 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
110 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
111 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
112 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
113 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
114 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
115 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
116 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
117 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
118 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
119 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
120 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
121 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
122 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
123 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
124 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
125 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
126 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
127 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
128 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
129 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
130 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
131 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
132 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
133 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
134 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
135 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
136 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
137 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
138 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
139 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
140 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
141 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
142 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
143 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
144 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
145 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
146 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
147 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
148 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
149 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
150 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
151 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
152 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
153 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
154 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
155 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
156 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
157 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
158 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
159 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
160 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
161 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
162 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
163 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
164 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
165 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
166 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
167 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
168 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
169 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
170 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
171 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
172 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
173 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
174 &Spell::EffectUnused, //112 SPELL_EFFECT_112
175 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
176 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
177 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
178 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
179 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
180 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
181 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
182 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
183 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
184 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
185 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
186 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
187 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
188 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
189 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
190 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
191 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
192 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
193 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
194 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
195 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
196 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
197 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
198 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
199 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
200 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
201 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
202 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
203 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
204 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
205 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
206 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
207 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
208 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
209 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
210 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
211 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
212 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
213 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
214 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
215 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
216 &Spell::EffectNULL, //154 unused
217 &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.
218 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
219 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
220 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
221 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
224 void Spell::EffectNULL(uint32 /*i*/)
226 sLog.outDebug("WORLD: Spell Effect DUMMY");
229 void Spell::EffectUnused(uint32 /*i*/)
231 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
234 void Spell::EffectResurrectNew(uint32 i)
236 if(!unitTarget || unitTarget->isAlive())
237 return;
239 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
240 return;
242 if(!unitTarget->IsInWorld())
243 return;
245 Player* pTarget = ((Player*)unitTarget);
247 if(pTarget->isRessurectRequested()) // already have one active request
248 return;
250 uint32 health = damage;
251 uint32 mana = m_spellInfo->EffectMiscValue[i];
252 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
253 SendResurrectRequest(pTarget);
256 void Spell::EffectInstaKill(uint32 /*i*/)
258 if( !unitTarget || !unitTarget->isAlive() )
259 return;
261 // Demonic Sacrifice
262 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
264 uint32 entry = unitTarget->GetEntry();
265 uint32 spellID;
266 switch(entry)
268 case 416: spellID=18789; break; //imp
269 case 417: spellID=18792; break; //fellhunter
270 case 1860: spellID=18790; break; //void
271 case 1863: spellID=18791; break; //succubus
272 case 17252: spellID=35701; break; //fellguard
273 default:
274 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
275 return;
278 m_caster->CastSpell(m_caster,spellID,true);
281 if(m_caster==unitTarget) // prevent interrupt message
282 finish();
284 uint32 health = unitTarget->GetHealth();
285 m_caster->DealDamage(unitTarget, health, 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->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[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(m_caster->GetGUID(),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 //Gore
314 if(m_spellInfo->SpellIconID == 2269 )
316 damage+= rand()%2 ? damage : 0;
319 switch(m_spellInfo->Id) // better way to check unknown
321 // Meteor like spells (divided damage to targets)
322 case 24340: case 26558: case 28884: // Meteor
323 case 36837: case 38903: case 41276: // Meteor
324 case 26789: // Shard of the Fallen Star
325 case 31436: // Malevolent Cleave
326 case 35181: // Dive Bomb
327 case 40810: case 43267: case 43268: // Saber Lash
328 case 42384: // Brutal Swipe
329 case 45150: // Meteor Slash
331 uint32 count = 0;
332 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
333 if(ihit->effectMask & (1<<effect_idx))
334 ++count;
336 damage /= count; // divide to all targets
337 break;
339 // percent from health with min
340 case 25599: // Thundercrash
342 damage = unitTarget->GetHealth() / 2;
343 if(damage < 200)
344 damage = 200;
345 break;
347 // Intercept (warrior spell trigger)
348 case 20253:
349 case 61491:
351 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
352 break;
355 break;
358 case SPELLFAMILY_MAGE:
360 // Arcane Blast
361 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
363 m_caster->CastSpell(m_caster,36032,true);
365 break;
367 case SPELLFAMILY_WARRIOR:
369 // Bloodthirst
370 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
372 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
374 // Shield Slam
375 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
376 damage += int32(m_caster->GetShieldBlockValue());
377 // Victory Rush
378 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
380 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
381 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
383 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
384 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
385 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
386 // Heroic Throw ${$m1+$AP*.50}
387 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
388 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
389 // Shockwave ${$m3/100*$AP}
390 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
392 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
393 if (pct > 0)
394 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
395 break;
397 break;
399 case SPELLFAMILY_WARLOCK:
401 // Incinerate Rank 1 & 2
402 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
404 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
405 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
406 damage += int32(damage*0.25f);
408 break;
410 case SPELLFAMILY_PRIEST:
412 // Shadow Word: Death - deals damage equal to damage done to caster
413 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
414 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
415 break;
417 case SPELLFAMILY_DRUID:
419 // Ferocious Bite
420 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
422 // converts each extra point of energy into ($f1+$AP/410) additional damage
423 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
424 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
425 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
426 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
427 m_caster->SetPower(POWER_ENERGY,0);
429 // Rake
430 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
432 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
434 // Swipe
435 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
437 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
439 //Mangle Bonus for the initial damage of Lacerate and Rake
440 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
441 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
443 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
444 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
445 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
447 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
448 break;
451 break;
453 case SPELLFAMILY_ROGUE:
455 // Envenom
456 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
458 // consume from stack dozes not more that have combo-points
459 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
461 Aura *poison = 0;
462 // Lookup for Deadly poison (only attacker applied)
463 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
464 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
465 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
466 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
467 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
469 poison = *itr;
470 break;
472 // count consumed deadly poison doses at target
473 if (poison)
475 uint32 spellId = poison->GetId();
476 uint32 doses = poison->GetStackAmount();
477 if (doses > combo)
478 doses = combo;
479 for (int i=0; i< doses; i++)
480 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
481 damage *= doses;
482 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
484 // Eviscerate and Envenom Bonus Damage (item set effect)
485 if(m_caster->GetDummyAura(37169))
486 damage += ((Player*)m_caster)->GetComboPoints()*40;
489 // Eviscerate
490 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
492 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
494 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
495 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
497 // Eviscerate and Envenom Bonus Damage (item set effect)
498 if(m_caster->GetDummyAura(37169))
499 damage += combo*40;
502 // Gouge
503 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
505 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
507 // Instant Poison
508 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
510 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
512 // Wound Poison
513 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
515 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
517 break;
519 case SPELLFAMILY_HUNTER:
521 // Mongoose Bite
522 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
524 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
526 // Counterattack
527 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
529 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
531 // Arcane Shot
532 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
534 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
536 // Steady Shot
537 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
539 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
540 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
542 // Explosive Trap Effect
543 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
545 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
547 break;
549 case SPELLFAMILY_PALADIN:
551 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
552 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
554 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
555 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
556 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
557 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
558 // Get stack of Holy Vengeance on the target added by caster
559 uint32 stacks = 0;
560 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
561 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
562 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
564 stacks = (*itr)->GetStackAmount();
565 break;
567 // + 10% for each application of Holy Vengeance on the target
568 if(stacks)
569 damage += damage * stacks * 10 /100;
571 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
572 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
574 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
575 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
576 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
577 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
579 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
580 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
582 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
583 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
584 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
585 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
587 // Hammer of the Righteous
588 else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL)
590 // Add main hand dps * effect[2] amount
591 float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
592 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
593 damage += count * int32(averange * 1000) / m_caster->GetAttackTime(BASE_ATTACK);
595 break;
599 if(damage >= 0)
600 m_damage+= damage;
604 void Spell::EffectDummy(uint32 i)
606 if(!unitTarget && !gameObjTarget && !itemTarget)
607 return;
609 // selection by spell family
610 switch(m_spellInfo->SpellFamilyName)
612 case SPELLFAMILY_GENERIC:
614 switch(m_spellInfo->Id )
616 case 8063: // Deviate Fish
618 if(m_caster->GetTypeId() != TYPEID_PLAYER)
619 return;
621 uint32 spell_id = 0;
622 switch(urand(1,5))
624 case 1: spell_id = 8064; break; // Sleepy
625 case 2: spell_id = 8065; break; // Invigorate
626 case 3: spell_id = 8066; break; // Shrink
627 case 4: spell_id = 8067; break; // Party Time!
628 case 5: spell_id = 8068; break; // Healthy Spirit
630 m_caster->CastSpell(m_caster,spell_id,true,NULL);
631 return;
633 case 8213: // Savory Deviate Delight
635 if(m_caster->GetTypeId() != TYPEID_PLAYER)
636 return;
638 uint32 spell_id = 0;
639 switch(urand(1,2))
641 // Flip Out - ninja
642 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
643 // Yaaarrrr - pirate
644 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
646 m_caster->CastSpell(m_caster,spell_id,true,NULL);
647 return;
649 case 8593: // Symbol of life (restore creature to life)
650 case 31225: // Shimmering Vessel (restore creature to life)
652 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
653 return;
654 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
655 return;
657 case 12162: // Deep wounds
658 case 12850: // (now good common check for this spells)
659 case 12868:
661 if(!unitTarget)
662 return;
664 float damage;
665 // DW should benefit of attack power, damage percent mods etc.
666 // TODO: check if using offhand damage is correct and if it should be divided by 2
667 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
668 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
669 else
670 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
672 switch (m_spellInfo->Id)
674 case 12850: damage *= 0.2f; break;
675 case 12162: damage *= 0.4f; break;
676 case 12868: damage *= 0.6f; break;
677 default:
678 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
679 return;
682 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
683 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
684 return;
686 case 13120: // net-o-matic
688 if(!unitTarget)
689 return;
691 uint32 spell_id = 0;
693 uint32 roll = urand(0, 99);
695 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
696 spell_id = 16566;
697 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
698 spell_id = 13119;
699 else // normal root
700 spell_id = 13099;
702 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
703 return;
705 case 13567: // Dummy Trigger
707 // can be used for different aura triggering, so select by aura
708 if(!m_triggeredByAuraSpell || !unitTarget)
709 return;
711 switch(m_triggeredByAuraSpell->Id)
713 case 26467: // Persistent Shield
714 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
715 break;
716 default:
717 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
718 break;
720 return;
722 case 15998: // Capture Worg Pup
723 case 29435: // Capture Female Kaliri Hatchling
725 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
726 return;
728 Creature* creatureTarget = (Creature*)unitTarget;
729 creatureTarget->setDeathState(JUST_DIED);
730 creatureTarget->RemoveCorpse();
731 creatureTarget->SetHealth(0); // just for nice GM-mode view
732 return;
734 case 16589: // Noggenfogger Elixir
736 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
737 return;
739 uint32 spell_id = 0;
740 switch(urand(1,3))
742 case 1: spell_id = 16595; break;
743 case 2: spell_id = 16593; break;
744 default:spell_id = 16591; break;
747 m_caster->CastSpell(m_caster,spell_id,true,NULL);
748 return;
750 case 17251: // Spirit Healer Res
752 if(!unitTarget || !m_originalCaster)
753 return;
755 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
757 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
758 data << unitTarget->GetGUID();
759 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
761 return;
763 case 17271: // Test Fetid Skull
765 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
766 return;
768 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
770 m_caster->CastSpell(m_caster,spell_id,true,NULL);
771 return;
773 case 20577: // Cannibalize
774 if (unitTarget)
775 m_caster->CastSpell(m_caster,20578,false,NULL);
776 return;
777 case 23019: // Crystal Prison Dummy DND
779 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
780 return;
782 Creature* creatureTarget = (Creature*)unitTarget;
783 if(creatureTarget->isPet())
784 return;
786 GameObject* pGameObj = new GameObject;
788 Map *map = creatureTarget->GetMap();
790 // create before death for get proper coordinates
791 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
792 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
793 creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) )
795 delete pGameObj;
796 return;
799 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
800 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
801 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
802 pGameObj->SetSpellId(m_spellInfo->Id);
804 creatureTarget->setDeathState(JUST_DIED);
805 creatureTarget->RemoveCorpse();
806 creatureTarget->SetHealth(0); // just for nice GM-mode view
808 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
809 map->Add(pGameObj);
811 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
812 data << uint64(pGameObj->GetGUID());
813 m_caster->SendMessageToSet(&data,true);
815 return;
817 case 23074: // Arcanite Dragonling
818 if (!m_CastItem) return;
819 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
820 return;
821 case 23075: // Mithril Mechanical Dragonling
822 if (!m_CastItem) return;
823 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
824 return;
825 case 23076: // Mechanical Dragonling
826 if (!m_CastItem) return;
827 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
828 return;
829 case 23133: // Gnomish Battle Chicken
830 if (!m_CastItem) return;
831 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
832 return;
833 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
835 int32 r = irand(0, 119);
836 if ( r < 20 ) // 1/6 polymorph
837 m_caster->CastSpell(m_caster,23444,true);
838 else if ( r < 100 ) // 4/6 evil twin
839 m_caster->CastSpell(m_caster,23445,true);
840 else // 1/6 miss the target
841 m_caster->CastSpell(m_caster,36902,true);
842 return;
844 case 23453: // Ultrasafe Transporter: Gadgetzan
845 if ( roll_chance_i(50) ) // success
846 m_caster->CastSpell(m_caster,23441,true);
847 else // failure
848 m_caster->CastSpell(m_caster,23446,true);
849 return;
850 case 23645: // Hourglass Sand
851 m_caster->RemoveAurasDueToSpell(23170);
852 return;
853 case 23725: // Gift of Life (warrior bwl trinket)
854 m_caster->CastSpell(m_caster,23782,true);
855 m_caster->CastSpell(m_caster,23783,true);
856 return;
857 case 25860: // Reindeer Transformation
859 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
860 return;
862 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
863 float speed = m_caster->GetSpeedRate(MOVE_RUN);
865 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
867 //5 different spells used depending on mounted speed and if mount can fly or not
868 if (flyspeed >= 4.1f)
869 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
870 else if (flyspeed >= 3.8f)
871 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
872 else if (flyspeed >= 1.6f)
873 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
874 else if (speed >= 2.0f)
875 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
876 else
877 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
879 return;
881 //case 26074: // Holiday Cheer
882 // return; -- implemented at client side
883 case 28006: // Arcane Cloaking
885 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
886 m_caster->CastSpell(unitTarget,29294,true);
887 return;
889 case 28730: // Arcane Torrent (Mana)
891 Aura * dummy = m_caster->GetDummyAura(28734);
892 if (dummy)
894 int32 bp = damage * dummy->GetStackAmount();
895 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
896 m_caster->RemoveAurasDueToSpell(28734);
898 return;
900 case 29200: // Purify Helboar Meat
902 if( m_caster->GetTypeId() != TYPEID_PLAYER )
903 return;
905 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
907 m_caster->CastSpell(m_caster,spell_id,true,NULL);
908 return;
910 case 29858: // Soulshatter
911 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
912 m_caster->CastSpell(unitTarget,32835,true);
913 return;
914 case 30458: // Nigh Invulnerability
915 if (!m_CastItem) return;
916 if(roll_chance_i(86)) // success
917 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
918 else // backfire in 14% casts
919 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
920 return;
921 case 30507: // Poultryizer
922 if (!m_CastItem) return;
923 if(roll_chance_i(80)) // success
924 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
925 else // backfire 20%
926 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
927 return;
928 case 33060: // Make a Wish
930 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
931 return;
933 uint32 spell_id = 0;
935 switch(urand(1,5))
937 case 1: spell_id = 33053; break;
938 case 2: spell_id = 33057; break;
939 case 3: spell_id = 33059; break;
940 case 4: spell_id = 33062; break;
941 case 5: spell_id = 33064; break;
944 m_caster->CastSpell(m_caster,spell_id,true,NULL);
945 return;
947 case 35745:
949 uint32 spell_id;
950 switch(m_caster->GetAreaId())
952 case 3900: spell_id = 35743; break;
953 case 3742: spell_id = 35744; break;
954 default: return;
957 m_caster->CastSpell(m_caster,spell_id,true);
958 return;
960 case 37674: // Chaos Blast
962 if(!unitTarget)
963 return;
965 int32 basepoints0 = 100;
966 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
967 return;
969 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
971 // selecting one from Bloodstained Fortune item
972 uint32 newitemid;
973 switch(urand(1,20))
975 case 1: newitemid = 32688; break;
976 case 2: newitemid = 32689; break;
977 case 3: newitemid = 32690; break;
978 case 4: newitemid = 32691; break;
979 case 5: newitemid = 32692; break;
980 case 6: newitemid = 32693; break;
981 case 7: newitemid = 32700; break;
982 case 8: newitemid = 32701; break;
983 case 9: newitemid = 32702; break;
984 case 10: newitemid = 32703; break;
985 case 11: newitemid = 32704; break;
986 case 12: newitemid = 32705; break;
987 case 13: newitemid = 32706; break;
988 case 14: newitemid = 32707; break;
989 case 15: newitemid = 32708; break;
990 case 16: newitemid = 32709; break;
991 case 17: newitemid = 32710; break;
992 case 18: newitemid = 32711; break;
993 case 19: newitemid = 32712; break;
994 case 20: newitemid = 32713; break;
995 default:
996 return;
999 DoCreateItem(i,newitemid);
1000 return;
1002 // Demon Broiled Surprise
1003 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1004 case 43723:
1006 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1007 return;
1009 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1010 return;
1013 case 44875: // Complete Raptor Capture
1015 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1016 return;
1018 Creature* creatureTarget = (Creature*)unitTarget;
1020 creatureTarget->setDeathState(JUST_DIED);
1021 creatureTarget->RemoveCorpse();
1022 creatureTarget->SetHealth(0); // just for nice GM-mode view
1024 //cast spell Raptor Capture Credit
1025 m_caster->CastSpell(m_caster,42337,true,NULL);
1026 return;
1028 case 37573: //Temporal Phase Modulator
1030 if(!unitTarget)
1031 return;
1033 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1034 if(!tempSummon)
1035 return;
1037 uint32 health = tempSummon->GetHealth();
1038 const uint32 entry_list[6] = {21821, 21820, 21817};
1040 float x = tempSummon->GetPositionX();
1041 float y = tempSummon->GetPositionY();
1042 float z = tempSummon->GetPositionZ();
1043 float o = tempSummon->GetOrientation();
1045 tempSummon->UnSummon();
1047 Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1048 if (!pCreature)
1049 return;
1051 pCreature->SetHealth(health);
1053 if(pCreature->AI())
1054 pCreature->AI()->AttackStart(m_caster);
1056 return;
1058 case 34665: //Administer Antidote
1060 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1061 return;
1063 if(!unitTarget)
1064 return;
1066 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1067 if(!tempSummon)
1068 return;
1070 uint32 health = tempSummon->GetHealth();
1072 float x = tempSummon->GetPositionX();
1073 float y = tempSummon->GetPositionY();
1074 float z = tempSummon->GetPositionZ();
1075 float o = tempSummon->GetOrientation();
1076 tempSummon->UnSummon();
1078 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1079 if (!pCreature)
1080 return;
1082 pCreature->SetHealth(health);
1083 ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1085 if (pCreature->AI())
1086 pCreature->AI()->AttackStart(m_caster);
1088 return;
1090 case 44997: // Converting Sentry
1092 //Converted Sentry Credit
1093 m_caster->CastSpell(m_caster, 45009, true);
1094 return;
1096 case 45030: // Impale Emissary
1098 // Emissary of Hate Credit
1099 m_caster->CastSpell(m_caster, 45088, true);
1100 return;
1102 case 50243: // Teach Language
1104 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1105 return;
1107 // spell has a 1/3 chance to trigger one of the below
1108 if(roll_chance_i(66))
1109 return;
1110 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1112 // 1000001 - gnomish binary
1113 m_caster->CastSpell(m_caster, 50242, true);
1115 else
1117 // 01001000 - goblin binary
1118 m_caster->CastSpell(m_caster, 50246, true);
1121 return;
1123 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1125 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1126 return;
1128 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1129 bg->EventPlayerDroppedFlag((Player*)m_caster);
1131 m_caster->CastSpell(m_caster, 30452, true, NULL);
1132 return;
1134 case 53341:
1135 case 53343:
1137 m_caster->CastSpell(m_caster,54586,true);
1138 return;
1142 //All IconID Check in there
1143 switch(m_spellInfo->SpellIconID)
1145 // Berserking (troll racial traits)
1146 case 1661:
1148 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1149 int32 melee_mod = 10;
1150 if (healthPerc <= 40)
1151 melee_mod = 30;
1152 if (healthPerc < 100 && healthPerc > 40)
1153 melee_mod = 10+(100-healthPerc)/3;
1155 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1156 int32 hasteModBasePoints1 = (5-melee_mod);
1157 int32 hasteModBasePoints2 = 5;
1159 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1160 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1161 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1162 return;
1165 break;
1167 case SPELLFAMILY_MAGE:
1168 switch(m_spellInfo->Id )
1170 case 11958: // Cold Snap
1172 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1173 return;
1175 // immediately finishes the cooldown on Frost spells
1176 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1177 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1179 if (itr->second->state == PLAYERSPELL_REMOVED)
1180 continue;
1182 uint32 classspell = itr->first;
1183 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1185 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1186 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1187 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1189 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1191 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1192 data << uint32(classspell);
1193 data << uint64(m_caster->GetGUID());
1194 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1197 return;
1199 case 32826:
1201 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1203 //Polymorph Cast Visual Rank 1
1204 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1205 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1207 return;
1210 break;
1211 case SPELLFAMILY_WARRIOR:
1212 // Charge
1213 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1215 int32 chargeBasePoints0 = damage;
1216 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1217 return;
1219 // Execute
1220 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1222 if(!unitTarget)
1223 return;
1225 uint32 rage = m_caster->GetPower(POWER_RAGE);
1226 // Glyph of Execution bonus
1227 if (Aura *aura = m_caster->GetDummyAura(58367))
1228 rage+=aura->GetModifier()->m_amount;
1230 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1231 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1232 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1233 m_caster->SetPower(POWER_RAGE,0);
1234 return;
1236 // Slam
1237 if(m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL)
1239 if(!unitTarget)
1240 return;
1241 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1242 m_damage+=damage;
1243 return;
1245 switch(m_spellInfo->Id)
1247 // Warrior's Wrath
1248 case 21977:
1250 if(!unitTarget)
1251 return;
1252 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1253 return;
1255 // Last Stand
1256 case 12975:
1258 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1259 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1260 return;
1262 // Bloodthirst
1263 case 23881:
1265 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1266 return;
1269 break;
1270 case SPELLFAMILY_WARLOCK:
1271 // Life Tap
1272 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1274 // In 303 exist spirit depend
1275 uint32 spirit = m_caster->GetStat(STAT_SPIRIT);
1276 switch (m_spellInfo->Id)
1278 case 1454: damage+=spirit; break;
1279 case 1455: damage+=spirit*15/10; break;
1280 case 1456: damage+=spirit*2; break;
1281 case 11687: damage+=spirit*25/10; break;
1282 case 11688:
1283 case 11689:
1284 case 27222:
1285 case 57946: damage+=spirit*3; break;
1286 default:
1287 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1288 return;
1290 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1291 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1292 if(int32(unitTarget->GetHealth()) > damage)
1294 // Shouldn't Appear in Combat Log
1295 unitTarget->ModifyHealth(-damage);
1297 int32 mana = damage;
1298 // Improved Life Tap mod
1299 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1300 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1302 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1303 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1305 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1307 // Mana Feed
1308 int32 manaFeedVal = 0;
1309 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1310 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1312 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1313 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1315 if(manaFeedVal > 0)
1317 manaFeedVal = manaFeedVal * mana / 100;
1318 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1321 else
1322 SendCastResult(SPELL_FAILED_FIZZLE);
1323 return;
1325 break;
1326 case SPELLFAMILY_PRIEST:
1327 // Penance
1328 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1330 if (!unitTarget)
1331 return;
1333 int hurt = 0;
1334 int heal = 0;
1335 switch(m_spellInfo->Id)
1337 case 47540: hurt = 47758; heal = 47757; break;
1338 case 53005: hurt = 53001; heal = 52986; break;
1339 case 53006: hurt = 53002; heal = 52987; break;
1340 case 53007: hurt = 53003; heal = 52988; break;
1341 default:
1342 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1343 return;
1345 if (m_caster->IsFriendlyTo(unitTarget))
1346 m_caster->CastSpell(unitTarget, heal, true, 0);
1347 else
1348 m_caster->CastSpell(unitTarget, hurt, true, 0);
1349 return;
1351 switch(m_spellInfo->Id )
1353 case 28598: // Touch of Weakness triggered spell
1355 if(!unitTarget || !m_triggeredByAuraSpell)
1356 return;
1358 uint32 spellid = 0;
1359 switch(m_triggeredByAuraSpell->Id)
1361 case 2652: spellid = 2943; break; // Rank 1
1362 case 19261: spellid = 19249; break; // Rank 2
1363 case 19262: spellid = 19251; break; // Rank 3
1364 case 19264: spellid = 19252; break; // Rank 4
1365 case 19265: spellid = 19253; break; // Rank 5
1366 case 19266: spellid = 19254; break; // Rank 6
1367 case 25461: spellid = 25460; break; // Rank 7
1368 default:
1369 sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1370 return;
1372 m_caster->CastSpell(unitTarget, spellid, true, NULL);
1373 return;
1376 break;
1377 case SPELLFAMILY_DRUID:
1378 break;
1379 case SPELLFAMILY_ROGUE:
1380 switch(m_spellInfo->Id )
1382 case 5938: // Shiv
1384 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1385 return;
1387 Player *pCaster = ((Player*)m_caster);
1389 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1390 if(!item)
1391 return;
1393 // all poison enchantments is temporary
1394 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1395 if(!enchant_id)
1396 return;
1398 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1399 if(!pEnchant)
1400 return;
1402 for (int s=0;s<3;s++)
1404 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1405 continue;
1407 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1408 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1409 continue;
1411 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1414 m_caster->CastSpell(unitTarget, 5940, true);
1415 return;
1417 case 14185: // Preparation Rogue
1419 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1420 return;
1422 //immediately finishes the cooldown on certain Rogue abilities
1423 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1424 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1426 uint32 classspell = itr->first;
1427 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1429 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1431 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1433 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1434 data << uint32(classspell);
1435 data << uint64(m_caster->GetGUID());
1436 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1439 return;
1441 case 31231: // Cheat Death
1443 m_caster->CastSpell(m_caster,45182,true);
1444 return;
1447 break;
1448 case SPELLFAMILY_HUNTER:
1449 // Steady Shot
1450 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1452 if( !unitTarget || !unitTarget->isAlive())
1453 return;
1455 bool found = false;
1457 // check dazed affect
1458 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1459 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1461 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1463 found = true;
1464 break;
1468 if(found)
1469 m_damage+= damage;
1470 return;
1473 switch(m_spellInfo->Id)
1475 case 23989: //Readiness talent
1477 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1478 return;
1480 //immediately finishes the cooldown for hunter abilities
1481 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1482 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1484 uint32 classspell = itr->first;
1485 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1487 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1489 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1491 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1492 data << uint32(classspell);
1493 data << uint64(m_caster->GetGUID());
1494 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1497 return;
1499 case 37506: // Scatter Shot
1501 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1502 return;
1504 // break Auto Shot and autohit
1505 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1506 m_caster->AttackStop();
1507 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1508 return;
1511 break;
1512 case SPELLFAMILY_PALADIN:
1513 switch(m_spellInfo->SpellIconID)
1515 case 156: // Holy Shock
1517 if(!unitTarget)
1518 return;
1520 int hurt = 0;
1521 int heal = 0;
1523 switch(m_spellInfo->Id)
1525 case 20473: hurt = 25912; heal = 25914; break;
1526 case 20929: hurt = 25911; heal = 25913; break;
1527 case 20930: hurt = 25902; heal = 25903; break;
1528 case 27174: hurt = 27176; heal = 27175; break;
1529 case 33072: hurt = 33073; heal = 33074; break;
1530 case 48824: hurt = 48822; heal = 48820; break;
1531 case 48825: hurt = 48823; heal = 48821; break;
1532 default:
1533 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1534 return;
1537 if(m_caster->IsFriendlyTo(unitTarget))
1538 m_caster->CastSpell(unitTarget, heal, true, 0);
1539 else
1540 m_caster->CastSpell(unitTarget, hurt, true, 0);
1542 return;
1544 case 561: // Judgement of command
1546 if(!unitTarget)
1547 return;
1549 uint32 spell_id = m_currentBasePoints[i]+1;
1550 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1551 if(!spell_proto)
1552 return;
1554 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1556 // decreased damage (/2) for non-stunned target.
1557 SpellModifier *mod = new SpellModifier;
1558 mod->op = SPELLMOD_DAMAGE;
1559 mod->value = -50;
1560 mod->type = SPELLMOD_PCT;
1561 mod->spellId = m_spellInfo->Id;
1562 mod->mask = 0x0000020000000000LL;
1563 mod->mask2= 0LL;
1565 ((Player*)m_caster)->AddSpellMod(mod, true);
1566 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1567 // mod deleted
1568 ((Player*)m_caster)->AddSpellMod(mod, false);
1570 else
1571 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1573 return;
1577 switch(m_spellInfo->Id)
1579 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1580 case 20187:
1582 if (!unitTarget)
1583 return;
1584 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1585 return;
1587 case 31789: // Righteous Defense (step 1)
1589 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1591 // non-standard cast requirement check
1592 if (!unitTarget || unitTarget->getAttackers().empty())
1594 // clear cooldown at fail
1595 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1597 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1599 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1600 data << uint32(m_spellInfo->Id);
1601 data << uint64(m_caster->GetGUID());
1602 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1605 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1606 return;
1609 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1610 // Clear targets for eff 1
1611 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1612 ihit->effectMask &= ~(1<<1);
1614 // not empty (checked)
1615 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1617 // chance to be selected from list
1618 float chance = 100.0f/attackers.size();
1619 uint32 count=0;
1620 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1622 if(!roll_chance_f(chance))
1623 continue;
1624 ++count;
1625 AddUnitTarget((*aItr), 1);
1628 // now let next effect cast spell at each target.
1629 return;
1631 case 37877: // Blessing of Faith
1633 if(!unitTarget)
1634 return;
1636 uint32 spell_id = 0;
1637 switch(unitTarget->getClass())
1639 case CLASS_DRUID: spell_id = 37878; break;
1640 case CLASS_PALADIN: spell_id = 37879; break;
1641 case CLASS_PRIEST: spell_id = 37880; break;
1642 case CLASS_SHAMAN: spell_id = 37881; break;
1643 default: return; // ignore for not healing classes
1646 m_caster->CastSpell(m_caster,spell_id,true);
1647 return;
1650 break;
1651 case SPELLFAMILY_SHAMAN:
1652 //Shaman Rockbiter Weapon
1653 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1655 // TODO: use expect spell for enchant (if exist talent)
1656 // In 3.0.3 no mods present for rockbiter
1657 uint32 spell_id = 0;
1658 switch(m_spellInfo->Id)
1660 case 8017: spell_id = 36494; break; // Rank 1
1661 case 8018: spell_id = 36750; break; // Rank 2
1662 case 8019: spell_id = 36755; break; // Rank 3
1663 case 10399: spell_id = 36759; break; // Rank 4
1664 default:
1665 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1666 return;
1669 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1671 if(!spellInfo)
1673 sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1674 return;
1677 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1678 return;
1680 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1682 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1684 if(item->IsFitToSpellRequirements(m_spellInfo))
1686 Spell *spell = new Spell(m_caster, spellInfo, true);
1688 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1689 // at calculation applied affect from Elemental Weapons talent
1690 // real enchantment damage-1
1691 spell->m_currentBasePoints[1] = damage-1;
1693 SpellCastTargets targets;
1694 targets.setItemTarget( item );
1695 spell->prepare(&targets);
1699 return;
1701 // Healing Stream Totem
1702 if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
1704 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1705 return;
1707 // Mana Spring Totem
1708 if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
1710 if(unitTarget->getPowerType()!=POWER_MANA)
1711 return;
1712 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1713 return;
1715 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1717 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1718 return;
1719 // Glyph of Mana Tide
1720 Unit *owner = m_caster->GetOwner();
1721 if (owner)
1722 if (Aura *dummy = owner->GetDummyAura(55441))
1723 damage+=dummy->GetModifier()->m_amount;
1724 // Regenerate 6% of Total Mana Every 3 secs
1725 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1726 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1727 return;
1729 // Lava Lash
1730 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1732 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1733 return;
1734 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1735 if (item)
1737 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1738 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1739 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1741 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1742 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1743 (*itr)->GetCastItemGUID() == item->GetGUID())
1745 m_damage += m_damage * damage / 100;
1746 return;
1750 return;
1752 break;
1755 // pet auras
1756 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1758 m_caster->AddPetAura(petSpell);
1759 return;
1763 void Spell::EffectTriggerSpellWithValue(uint32 i)
1765 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1767 // normal case
1768 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1770 if(!spellInfo)
1772 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1773 return;
1776 int32 bp = damage;
1777 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1780 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1782 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1783 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1785 if(!spellInfo)
1787 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1788 return;
1791 finish();
1792 Spell *spell = new Spell(m_caster, spellInfo, true);
1794 SpellCastTargets targets;
1795 targets.setUnitTarget( unitTarget);
1796 spell->prepare(&targets);
1798 m_caster->SetCurrentCastedSpell(spell);
1799 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1803 void Spell::EffectForceCast(uint32 i)
1805 if( !unitTarget )
1806 return;
1808 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1810 // normal case
1811 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1813 if(!spellInfo)
1815 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1816 return;
1819 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1822 void Spell::EffectTriggerSpell(uint32 i)
1824 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1826 // special cases
1827 switch(triggered_spell_id)
1829 // Vanish
1830 case 18461:
1832 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1833 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1834 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1836 // if this spell is given to NPC it must handle rest by it's own AI
1837 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1838 return;
1840 // get highest rank of the Stealth spell
1841 uint32 spellId = 0;
1842 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1843 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1845 // only highest rank is shown in spell book, so simply check if shown in spell book
1846 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1847 continue;
1849 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1850 if (!spellInfo)
1851 continue;
1853 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1855 spellId = spellInfo->Id;
1856 break;
1860 // no Stealth spell found
1861 if (!spellId)
1862 return;
1864 // reset cooldown on it if needed
1865 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1866 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1868 m_caster->CastSpell(m_caster, spellId, true);
1869 return;
1871 // just skip
1872 case 23770: // Sayge's Dark Fortune of *
1873 // not exist, common cooldown can be implemented in scripts if need.
1874 return;
1875 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1876 case 29284:
1878 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1879 if (!spell)
1880 return;
1882 for (int i=0; i < spell->StackAmount; ++i)
1883 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1884 return;
1886 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1887 case 29286:
1889 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1890 if (!spell)
1891 return;
1893 for (int i=0; i < spell->StackAmount; ++i)
1894 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1895 return;
1897 // Righteous Defense
1898 case 31980:
1900 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1901 return;
1903 // Cloak of Shadows
1904 case 35729 :
1906 Unit::AuraMap& Auras = m_caster->GetAuras();
1907 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1909 // remove all harmful spells on you...
1910 if( // ignore positive and passive auras
1911 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1912 // ignore physical auras
1913 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1915 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1916 iter = Auras.begin();
1919 return;
1921 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1922 case 41967:
1924 if (Unit *pet = m_caster->GetPet())
1925 pet->CastSpell(pet, 28305, true);
1926 return;
1930 // normal case
1931 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1933 if(!spellInfo)
1935 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1936 return;
1939 // some triggered spells require specific equipment
1940 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1942 // main hand weapon required
1943 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1945 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1947 // skip spell if no weapon in slot or broken
1948 if(!item || item->IsBroken() )
1949 return;
1951 // skip spell if weapon not fit to triggered spell
1952 if(!item->IsFitToSpellRequirements(spellInfo))
1953 return;
1956 // offhand hand weapon required
1957 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1959 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1961 // skip spell if no weapon in slot or broken
1962 if(!item || item->IsBroken() )
1963 return;
1965 // skip spell if weapon not fit to triggered spell
1966 if(!item->IsFitToSpellRequirements(spellInfo))
1967 return;
1971 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1972 bool instant = false;
1973 for(uint32 j = i+1; j < 3; ++j)
1975 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1977 instant = true;
1978 break;
1982 if(instant)
1984 if (unitTarget)
1985 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1987 else
1988 m_TriggerSpells.push_back(spellInfo);
1991 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1993 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1995 // normal case
1996 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1998 if(!spellInfo)
2000 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2001 m_spellInfo->Id,effect_idx,triggered_spell_id);
2002 return;
2005 if (m_CastItem)
2006 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2008 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2011 void Spell::EffectTeleportUnits(uint32 i)
2013 if(!unitTarget || unitTarget->isInFlight())
2014 return;
2016 switch (m_spellInfo->EffectImplicitTargetB[i])
2018 case TARGET_INNKEEPER_COORDINATES:
2020 // Only players can teleport to innkeeper
2021 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2022 return;
2024 ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
2025 return;
2027 case TARGET_TABLE_X_Y_Z_COORDINATES:
2029 // TODO: Only players can teleport?
2030 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2031 return;
2032 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2033 if(!st)
2035 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
2036 return;
2038 ((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);
2039 break;
2041 case TARGET_BEHIND_VICTIM:
2043 // Get selected target for player (or victim for units)
2044 Unit *pTarget = NULL;
2045 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2046 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2047 else
2048 pTarget = m_caster->getVictim();
2049 // No target present - return
2050 if (!pTarget)
2051 return;
2052 // Init dest coordinates
2053 uint32 mapid = m_caster->GetMapId();
2054 float x = m_targets.m_destX;
2055 float y = m_targets.m_destY;
2056 float z = m_targets.m_destZ;
2057 float orientation = pTarget->GetOrientation();
2058 // Teleport
2059 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2060 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2061 else
2063 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2064 WorldPacket data;
2065 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2066 unitTarget->SendMessageToSet(&data, false);
2068 return;
2070 default:
2072 // If not exist data for dest location - return
2073 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2075 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2076 return;
2078 // Init dest coordinates
2079 uint32 mapid = m_caster->GetMapId();
2080 float x = m_targets.m_destX;
2081 float y = m_targets.m_destY;
2082 float z = m_targets.m_destZ;
2083 float orientation = unitTarget->GetOrientation();
2084 // Teleport
2085 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2086 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2087 else
2089 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2090 WorldPacket data;
2091 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2092 unitTarget->SendMessageToSet(&data, false);
2094 return;
2098 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2099 switch ( m_spellInfo->Id )
2101 // Dimensional Ripper - Everlook
2102 case 23442:
2104 int32 r = irand(0, 119);
2105 if ( r >= 70 ) // 7/12 success
2107 if ( r < 100 ) // 4/12 evil twin
2108 m_caster->CastSpell(m_caster,23445,true);
2109 else // 1/12 fire
2110 m_caster->CastSpell(m_caster,23449,true);
2112 return;
2114 // Ultrasafe Transporter: Toshley's Station
2115 case 36941:
2117 if ( roll_chance_i(50) ) // 50% success
2119 int32 rand_eff = urand(1,7);
2120 switch ( rand_eff )
2122 case 1:
2123 // soul split - evil
2124 m_caster->CastSpell(m_caster,36900,true);
2125 break;
2126 case 2:
2127 // soul split - good
2128 m_caster->CastSpell(m_caster,36901,true);
2129 break;
2130 case 3:
2131 // Increase the size
2132 m_caster->CastSpell(m_caster,36895,true);
2133 break;
2134 case 4:
2135 // Decrease the size
2136 m_caster->CastSpell(m_caster,36893,true);
2137 break;
2138 case 5:
2139 // Transform
2141 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2142 m_caster->CastSpell(m_caster,36897,true);
2143 else
2144 m_caster->CastSpell(m_caster,36899,true);
2145 break;
2147 case 6:
2148 // chicken
2149 m_caster->CastSpell(m_caster,36940,true);
2150 break;
2151 case 7:
2152 // evil twin
2153 m_caster->CastSpell(m_caster,23445,true);
2154 break;
2157 return;
2159 // Dimensional Ripper - Area 52
2160 case 36890:
2162 if ( roll_chance_i(50) ) // 50% success
2164 int32 rand_eff = urand(1,4);
2165 switch ( rand_eff )
2167 case 1:
2168 // soul split - evil
2169 m_caster->CastSpell(m_caster,36900,true);
2170 break;
2171 case 2:
2172 // soul split - good
2173 m_caster->CastSpell(m_caster,36901,true);
2174 break;
2175 case 3:
2176 // Increase the size
2177 m_caster->CastSpell(m_caster,36895,true);
2178 break;
2179 case 4:
2180 // Transform
2182 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2183 m_caster->CastSpell(m_caster,36897,true);
2184 else
2185 m_caster->CastSpell(m_caster,36899,true);
2186 break;
2190 return;
2195 void Spell::EffectApplyAura(uint32 i)
2197 if(!unitTarget)
2198 return;
2200 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2201 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2202 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2203 return;
2205 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2206 if(!caster)
2207 return;
2209 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2211 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2213 // Now Reduce spell duration using data received at spell hit
2214 int32 duration = Aur->GetAuraMaxDuration();
2215 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2216 Aur->setDiminishGroup(m_diminishGroup);
2218 // if Aura removed and deleted, do not continue.
2219 if(duration== 0 && !(Aur->IsPermanent()))
2221 delete Aur;
2222 return;
2225 if(duration != Aur->GetAuraMaxDuration())
2227 Aur->SetAuraMaxDuration(duration);
2228 Aur->SetAuraDuration(duration);
2231 bool added = unitTarget->AddAura(Aur);
2233 // Aura not added and deleted in AddAura call;
2234 if (!added)
2235 return;
2237 // found crash at character loading, broken pointer to Aur...
2238 // Aur was deleted in AddAura()...
2239 if(!Aur)
2240 return;
2242 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2243 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2244 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2247 void Spell::EffectUnlearnSpecialization( uint32 i )
2249 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2250 return;
2252 Player *_player = (Player*)unitTarget;
2253 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2255 _player->removeSpell(spellToUnlearn);
2257 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2260 void Spell::EffectPowerDrain(uint32 i)
2262 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2263 return;
2265 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2267 if(!unitTarget)
2268 return;
2269 if(!unitTarget->isAlive())
2270 return;
2271 if(unitTarget->getPowerType() != drain_power)
2272 return;
2273 if(damage < 0)
2274 return;
2276 uint32 curPower = unitTarget->GetPower(drain_power);
2278 //add spell damage bonus
2279 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2281 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2282 uint32 power = damage;
2283 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2284 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2286 int32 new_damage;
2287 if(curPower < power)
2288 new_damage = curPower;
2289 else
2290 new_damage = power;
2292 unitTarget->ModifyPower(drain_power,-new_damage);
2294 // Don`t restore from self drain
2295 if(drain_power == POWER_MANA && m_caster != unitTarget)
2297 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2298 if(manaMultiplier==0)
2299 manaMultiplier = 1;
2301 if(Player *modOwner = m_caster->GetSpellModOwner())
2302 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2304 int32 gain = int32(new_damage*manaMultiplier);
2306 m_caster->ModifyPower(POWER_MANA,gain);
2307 //send log
2308 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2312 void Spell::EffectSendEvent(uint32 EffectIndex)
2314 if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2316 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2317 if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2319 switch(m_spellInfo->Id)
2321 case 23333: // Pickup Horde Flag
2322 /*do not uncomment .
2323 if(bg->GetTypeID()==BATTLEGROUND_WS)
2324 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2325 sLog.outDebug("Send Event Horde Flag Picked Up");
2326 break;
2327 /* not used :
2328 case 23334: // Drop Horde Flag
2329 if(bg->GetTypeID()==BATTLEGROUND_WS)
2330 bg->EventPlayerDroppedFlag((Player*)m_caster);
2331 sLog.outDebug("Drop Horde Flag");
2332 break;
2334 case 23335: // Pickup Alliance Flag
2335 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2336 if(bg->GetTypeID()==BATTLEGROUND_WS)
2337 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2338 sLog.outDebug("Send Event Alliance Flag Picked Up");
2339 break;
2340 /* not used :
2341 case 23336: // Drop Alliance Flag
2342 if(bg->GetTypeID()==BATTLEGROUND_WS)
2343 bg->EventPlayerDroppedFlag((Player*)m_caster);
2344 sLog.outDebug("Drop Alliance Flag");
2345 break;
2346 case 23385: // Alliance Flag Returns
2347 if(bg->GetTypeID()==BATTLEGROUND_WS)
2348 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2349 sLog.outDebug("Alliance Flag Returned");
2350 break;
2351 case 23386: // Horde Flag Returns
2352 if(bg->GetTypeID()==BATTLEGROUND_WS)
2353 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2354 sLog.outDebug("Horde Flag Returned");
2355 break;*/
2356 case 34976:
2358 if(bg->GetTypeID()==BATTLEGROUND_EY)
2359 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2361 break;
2362 default:
2363 sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2364 break;
2368 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2369 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2372 void Spell::EffectPowerBurn(uint32 i)
2374 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2375 return;
2377 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2379 if(!unitTarget)
2380 return;
2381 if(!unitTarget->isAlive())
2382 return;
2383 if(unitTarget->getPowerType()!=powertype)
2384 return;
2385 if(damage < 0)
2386 return;
2388 int32 curPower = int32(unitTarget->GetPower(powertype));
2390 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2391 uint32 power = damage;
2392 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2393 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2395 int32 new_damage = (curPower < power) ? curPower : power;
2397 unitTarget->ModifyPower(powertype,-new_damage);
2398 float multiplier = m_spellInfo->EffectMultipleValue[i];
2400 if(Player *modOwner = m_caster->GetSpellModOwner())
2401 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2403 new_damage = int32(new_damage*multiplier);
2404 m_damage+=new_damage;
2407 void Spell::EffectHeal( uint32 /*i*/ )
2409 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2411 // Try to get original caster
2412 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2414 // Skip if m_originalCaster not available
2415 if (!caster)
2416 return;
2418 int32 addhealth = damage;
2420 // Vessel of the Naaru (Vial of the Sunwell trinket)
2421 if (m_spellInfo->Id == 45064)
2423 // Amount of heal - depends from stacked Holy Energy
2424 int damageAmount = 0;
2425 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2426 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2427 if((*i)->GetId() == 45062)
2428 damageAmount+=(*i)->GetModifier()->m_amount;
2429 if (damageAmount)
2430 m_caster->RemoveAurasDueToSpell(45062);
2432 addhealth += damageAmount;
2434 // Swiftmend - consumes Regrowth or Rejuvenation
2435 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2437 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2438 // find most short by duration
2439 Aura *targetAura = NULL;
2440 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2442 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2443 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2445 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2446 targetAura = *i;
2450 if(!targetAura)
2452 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2453 return;
2455 int idx = 0;
2456 while(idx < 3)
2458 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2459 break;
2460 idx++;
2463 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2464 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2465 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2467 addhealth += tickheal * tickcount;
2469 else
2470 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2472 m_healing+=addhealth;
2476 void Spell::EffectHealPct( uint32 /*i*/ )
2478 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2480 // Try to get original caster
2481 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2483 // Skip if m_originalCaster not available
2484 if (!caster)
2485 return;
2487 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2488 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2490 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2491 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2493 if(caster->GetTypeId()==TYPEID_PLAYER)
2494 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2495 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2499 void Spell::EffectHealMechanical( uint32 /*i*/ )
2501 // Mechanic creature type should be correctly checked by targetCreatureType field
2502 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2504 // Try to get original caster
2505 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2507 // Skip if m_originalCaster not available
2508 if (!caster)
2509 return;
2511 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2512 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2513 unitTarget->ModifyHealth( int32(damage) );
2517 void Spell::EffectHealthLeech(uint32 i)
2519 if(!unitTarget)
2520 return;
2521 if(!unitTarget->isAlive())
2522 return;
2524 if(damage < 0)
2525 return;
2527 sLog.outDebug("HealthLeech :%i", damage);
2529 float multiplier = m_spellInfo->EffectMultipleValue[i];
2531 if(Player *modOwner = m_caster->GetSpellModOwner())
2532 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2534 int32 new_damage = int32(damage*multiplier);
2535 uint32 curHealth = unitTarget->GetHealth();
2536 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2537 if(curHealth < new_damage)
2538 new_damage = curHealth;
2540 if(m_caster->isAlive())
2542 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2544 m_caster->ModifyHealth(new_damage);
2546 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2547 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2549 // m_healthLeech+=tmpvalue;
2550 // m_damage+=new_damage;
2553 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2555 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2556 return;
2558 Player* player = (Player*)unitTarget;
2560 uint32 newitemid = itemtype;
2561 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2562 if(!pProto)
2564 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2565 return;
2568 uint32 num_to_add;
2570 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2571 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2573 int32 basePoints = m_currentBasePoints[i];
2574 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2575 if (randomPoints)
2576 num_to_add = basePoints + irand(1, randomPoints);
2577 else
2578 num_to_add = basePoints + 1;
2580 else if (pProto->MaxCount == 1)
2581 num_to_add = 1;
2582 else if(player->getLevel() >= m_spellInfo->spellLevel)
2584 int32 basePoints = m_currentBasePoints[i];
2585 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2586 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2588 else
2589 num_to_add = 2;
2591 if (num_to_add < 1)
2592 num_to_add = 1;
2593 if (num_to_add > pProto->GetMaxStackSize())
2594 num_to_add = pProto->GetMaxStackSize();
2596 // init items_count to 1, since 1 item will be created regardless of specialization
2597 int items_count=1;
2598 // the chance to create additional items
2599 float additionalCreateChance=0.0f;
2600 // the maximum number of created additional items
2601 uint8 additionalMaxNum=0;
2602 // get the chance and maximum number for creating extra items
2603 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2605 // roll with this chance till we roll not to create or we create the max num
2606 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2607 ++items_count;
2610 // really will be created more items
2611 num_to_add *= items_count;
2613 // can the player store the new item?
2614 ItemPosCountVec dest;
2615 uint32 no_space = 0;
2616 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2617 if( msg != EQUIP_ERR_OK )
2619 // convert to possible store amount
2620 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2621 num_to_add -= no_space;
2622 else
2624 // if not created by another reason from full inventory or unique items amount limitation
2625 player->SendEquipError( msg, NULL, NULL );
2626 return;
2630 if(num_to_add)
2632 // create the new item and store it
2633 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2635 // was it successful? return error if not
2636 if(!pItem)
2638 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2639 return;
2642 // set the "Crafted by ..." property of the item
2643 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2644 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2646 // send info to the client
2647 if(pItem)
2648 player->SendNewItem(pItem, num_to_add, true, true);
2650 // we succeeded in creating at least one item, so a levelup is possible
2651 player->UpdateCraftSkill(m_spellInfo->Id);
2654 // for battleground marks send by mail if not add all expected
2655 if(no_space > 0 )
2657 BattleGroundTypeId bgType;
2658 switch(m_spellInfo->Id)
2660 case SPELL_AV_MARK_WINNER:
2661 case SPELL_AV_MARK_LOSER:
2662 bgType = BATTLEGROUND_AV;
2663 break;
2664 case SPELL_WS_MARK_WINNER:
2665 case SPELL_WS_MARK_LOSER:
2666 bgType = BATTLEGROUND_WS;
2667 break;
2668 case SPELL_AB_MARK_WINNER:
2669 case SPELL_AB_MARK_LOSER:
2670 bgType = BATTLEGROUND_AB;
2671 break;
2672 default:
2673 return;
2676 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2677 bg->SendRewardMarkByMail(player,newitemid,no_space);
2681 void Spell::EffectCreateItem(uint32 i)
2683 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2686 void Spell::EffectCreateItem2(uint32 i)
2688 // special case: generate using spell_loot_template
2689 if(!m_spellInfo->EffectItemType[i])
2691 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2692 return;
2694 // create some random items
2695 ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
2696 return;
2698 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2701 void Spell::EffectPersistentAA(uint32 i)
2703 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2705 if(Player* modOwner = m_caster->GetSpellModOwner())
2706 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2708 int32 duration = GetSpellDuration(m_spellInfo);
2709 DynamicObject* dynObj = new DynamicObject;
2710 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2712 delete dynObj;
2713 return;
2715 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2716 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2717 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2718 m_caster->AddDynObject(dynObj);
2719 dynObj->GetMap()->Add(dynObj);
2722 void Spell::EffectEnergize(uint32 i)
2724 if(!unitTarget)
2725 return;
2726 if(!unitTarget->isAlive())
2727 return;
2729 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2730 return;
2732 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2734 // Some level depends spells
2735 int multiplier = 0;
2736 int level_diff = 0;
2737 switch (m_spellInfo->Id)
2739 // Restore Energy
2740 case 9512:
2741 level_diff = m_caster->getLevel() - 40;
2742 multiplier = 2;
2743 break;
2744 // Blood Fury
2745 case 24571:
2746 level_diff = m_caster->getLevel() - 60;
2747 multiplier = 10;
2748 break;
2749 // Burst of Energy
2750 case 24532:
2751 level_diff = m_caster->getLevel() - 60;
2752 multiplier = 4;
2753 break;
2754 default:
2755 break;
2758 if (level_diff > 0)
2759 damage -= multiplier * level_diff;
2761 if(damage < 0)
2762 return;
2764 if(unitTarget->GetMaxPower(power) == 0)
2765 return;
2767 unitTarget->ModifyPower(power,damage);
2768 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2770 // Mad Alchemist's Potion
2771 if (m_spellInfo->Id == 45051)
2773 // find elixirs on target
2774 uint32 elixir_mask = 0;
2775 Unit::AuraMap& Auras = unitTarget->GetAuras();
2776 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2778 uint32 spell_id = itr->second->GetId();
2779 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2780 elixir_mask |= mask;
2783 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2784 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2786 // get all available elixirs by mask and spell level
2787 std::vector<uint32> elixirs;
2788 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2789 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2791 if (itr->second & elixir_mask)
2793 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2794 continue;
2796 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2797 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2798 continue;
2800 elixirs.push_back(itr->first);
2804 if (!elixirs.empty())
2806 // cast random elixir on target
2807 uint32 rand_spell = urand(0,elixirs.size()-1);
2808 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2813 void Spell::EffectEnergisePct(uint32 i)
2815 if(!unitTarget)
2816 return;
2817 if(!unitTarget->isAlive())
2818 return;
2820 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2821 return;
2823 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2825 uint32 maxPower = unitTarget->GetMaxPower(power);
2826 if(maxPower == 0)
2827 return;
2829 uint32 gain = damage * maxPower / 100;
2830 unitTarget->ModifyPower(power, gain);
2831 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2834 void Spell::SendLoot(uint64 guid, LootType loottype)
2836 Player* player = (Player*)m_caster;
2837 if (!player)
2838 return;
2840 if (gameObjTarget)
2842 if (Script->GOHello(player, gameObjTarget))
2843 return;
2845 switch (gameObjTarget->GetGoType())
2847 case GAMEOBJECT_TYPE_DOOR:
2848 case GAMEOBJECT_TYPE_BUTTON:
2849 gameObjTarget->UseDoorOrButton();
2850 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2851 return;
2853 case GAMEOBJECT_TYPE_QUESTGIVER:
2854 // start or end quest
2855 player->PrepareQuestMenu(guid);
2856 player->SendPreparedQuest(guid);
2857 return;
2859 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2860 // triggering linked GO
2861 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2862 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2863 return;
2865 case GAMEOBJECT_TYPE_GOOBER:
2866 // goober_scripts can be triggered if the player don't have the quest
2867 if (gameObjTarget->GetGOInfo()->goober.eventId)
2869 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2870 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2873 // cast goober spell
2874 if (gameObjTarget->GetGOInfo()->goober.questId)
2875 ///Quest require to be active for GO using
2876 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2877 return;
2879 gameObjTarget->AddUniqueUse(player);
2880 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2882 //TODO? Objective counting called without spell check but with quest objective check
2883 // if send spell id then this line will duplicate to spell casting call (double counting)
2884 // So we or have this line and not required in quest_template have reqSpellIdN
2885 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2886 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2888 // triggering linked GO
2889 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2890 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2892 return;
2894 case GAMEOBJECT_TYPE_CHEST:
2895 // TODO: possible must be moved to loot release (in different from linked triggering)
2896 if (gameObjTarget->GetGOInfo()->chest.eventId)
2898 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2899 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2902 // triggering linked GO
2903 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2904 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2906 // Don't return, let loots been taken
2910 // Send loot
2911 player->SendLoot(guid, loottype);
2914 void Spell::EffectOpenLock(uint32 /*i*/)
2916 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2918 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2919 return;
2922 Player* player = (Player*)m_caster;
2924 LootType loottype = LOOT_CORPSE;
2925 uint32 lockId = 0;
2926 uint64 guid = 0;
2928 // Get lockId
2929 if(gameObjTarget)
2931 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2932 // Arathi Basin banner opening !
2933 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2934 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2936 //isAllowUseBattleGroundObject() already called in CanCast()
2937 // in battleground check
2938 if(BattleGround *bg = player->GetBattleGround())
2940 // check if it's correct bg
2941 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2942 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2943 return;
2946 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2948 //isAllowUseBattleGroundObject() already called in CanCast()
2949 // in battleground check
2950 if(BattleGround *bg = player->GetBattleGround())
2952 if(bg->GetTypeID() == BATTLEGROUND_EY)
2953 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2954 return;
2957 lockId = gameObjTarget->GetLockId();
2958 guid = gameObjTarget->GetGUID();
2960 else if(itemTarget)
2962 lockId = itemTarget->GetProto()->LockID;
2963 guid = itemTarget->GetGUID();
2965 else
2967 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2968 return;
2971 if(!lockId) // possible case for GO and maybe for items.
2973 SendLoot(guid, loottype);
2974 return;
2977 // Get LockInfo
2978 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2980 if (!lockInfo)
2982 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2983 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2984 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2985 return;
2988 // check key
2989 for(int i = 0; i < 8; ++i)
2991 // Type==1 This means lockInfo->Index[i] is an item
2992 if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
2994 SendLoot(guid, loottype);
2995 return;
2999 uint32 SkillId = 0;
3000 // Check and skill-up skill
3001 if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
3002 SkillId = m_spellInfo->EffectMiscValue[1];
3003 // pickpocketing spells
3004 else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
3005 SkillId = SKILL_LOCKPICKING;
3007 // skill bonus provided by casting spell (mostly item spells)
3008 uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
3010 uint32 reqSkillValue = lockInfo->Skill[0];
3012 if(lockInfo->Skill[1]) // required pick lock skill applying
3014 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
3016 SendCastResult(SPELL_FAILED_FIZZLE);
3017 return;
3020 reqSkillValue = lockInfo->Skill[1];
3022 else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
3024 SendCastResult(SPELL_FAILED_BAD_TARGETS);
3025 return;
3028 if ( SkillId )
3030 loottype = LOOT_SKINNING;
3031 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
3033 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
3034 return;
3037 // update skill if really known
3038 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3039 if(SkillValue) // non only item base skill
3041 if(gameObjTarget)
3043 // Allow one skill-up until respawned
3044 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3045 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
3046 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3048 else if(itemTarget)
3050 // Do one skill-up
3051 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3052 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3057 SendLoot(guid, loottype);
3060 void Spell::EffectSummonChangeItem(uint32 i)
3062 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3063 return;
3065 Player *player = (Player*)m_caster;
3067 // applied only to using item
3068 if(!m_CastItem)
3069 return;
3071 // ... only to item in own inventory/bank/equip_slot
3072 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3073 return;
3075 uint32 newitemid = m_spellInfo->EffectItemType[i];
3076 if(!newitemid)
3077 return;
3079 uint16 pos = m_CastItem->GetPos();
3081 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3082 if( !pNewItem )
3083 return;
3085 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3087 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3088 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3091 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3093 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3094 player->DurabilityLoss(pNewItem, loosePercent);
3097 if( player->IsInventoryPos( pos ) )
3099 ItemPosCountVec dest;
3100 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3101 if( msg == EQUIP_ERR_OK )
3103 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3105 // prevent crash at access and unexpected charges counting with item update queue corrupt
3106 if(m_CastItem==m_targets.getItemTarget())
3107 m_targets.setItemTarget(NULL);
3109 m_CastItem = NULL;
3111 player->StoreItem( dest, pNewItem, true);
3112 return;
3115 else if( player->IsBankPos ( pos ) )
3117 ItemPosCountVec dest;
3118 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3119 if( msg == EQUIP_ERR_OK )
3121 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3123 // prevent crash at access and unexpected charges counting with item update queue corrupt
3124 if(m_CastItem==m_targets.getItemTarget())
3125 m_targets.setItemTarget(NULL);
3127 m_CastItem = NULL;
3129 player->BankItem( dest, pNewItem, true);
3130 return;
3133 else if( player->IsEquipmentPos ( pos ) )
3135 uint16 dest;
3136 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3137 if( msg == EQUIP_ERR_OK )
3139 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3141 // prevent crash at access and unexpected charges counting with item update queue corrupt
3142 if(m_CastItem==m_targets.getItemTarget())
3143 m_targets.setItemTarget(NULL);
3145 m_CastItem = NULL;
3147 player->EquipItem( dest, pNewItem, true);
3148 player->AutoUnequipOffhandIfNeed();
3149 return;
3153 // fail
3154 delete pNewItem;
3157 void Spell::EffectOpenSecretSafe(uint32 i)
3159 EffectOpenLock(i); //no difference for now
3162 void Spell::EffectProficiency(uint32 /*i*/)
3164 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3165 return;
3166 Player *p_target = (Player*)unitTarget;
3168 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3169 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3171 p_target->AddWeaponProficiency(subClassMask);
3172 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3174 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3176 p_target->AddArmorProficiency(subClassMask);
3177 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3181 void Spell::EffectApplyAreaAura(uint32 i)
3183 if(!unitTarget)
3184 return;
3185 if(!unitTarget->isAlive())
3186 return;
3188 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3189 unitTarget->AddAura(Aur);
3192 void Spell::EffectSummonType(uint32 i)
3194 switch(m_spellInfo->EffectMiscValueB[i])
3196 case SUMMON_TYPE_GUARDIAN:
3197 case SUMMON_TYPE_POSESSED:
3198 case SUMMON_TYPE_POSESSED2:
3199 case SUMMON_TYPE_FORCE_OF_NATURE:
3200 case SUMMON_TYPE_GUARDIAN2:
3201 EffectSummonGuardian(i);
3202 break;
3203 case SUMMON_TYPE_WILD:
3204 EffectSummonWild(i);
3205 break;
3206 case SUMMON_TYPE_DEMON:
3207 EffectSummonDemon(i);
3208 break;
3209 case SUMMON_TYPE_SUMMON:
3210 EffectSummon(i);
3211 break;
3212 case SUMMON_TYPE_CRITTER:
3213 case SUMMON_TYPE_CRITTER2:
3214 case SUMMON_TYPE_CRITTER3:
3215 EffectSummonCritter(i);
3216 break;
3217 case SUMMON_TYPE_TOTEM_SLOT1:
3218 case SUMMON_TYPE_TOTEM_SLOT2:
3219 case SUMMON_TYPE_TOTEM_SLOT3:
3220 case SUMMON_TYPE_TOTEM_SLOT4:
3221 case SUMMON_TYPE_TOTEM:
3222 EffectSummonTotem(i);
3223 break;
3224 case SUMMON_TYPE_UNKNOWN1:
3225 case SUMMON_TYPE_UNKNOWN2:
3226 case SUMMON_TYPE_UNKNOWN3:
3227 case SUMMON_TYPE_UNKNOWN4:
3228 case SUMMON_TYPE_UNKNOWN5:
3229 break;
3230 default:
3231 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3232 break;
3236 void Spell::EffectSummon(uint32 i)
3238 if(m_caster->GetPetGUID())
3239 return;
3241 if(!unitTarget)
3242 return;
3243 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3244 if(!pet_entry)
3245 return;
3246 uint32 level = m_caster->getLevel();
3247 Pet* spawnCreature = new Pet(SUMMON_PET);
3249 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3251 // set timer for unsummon
3252 int32 duration = GetSpellDuration(m_spellInfo);
3253 if(duration > 0)
3254 spawnCreature->SetDuration(duration);
3256 return;
3259 Map *map = m_caster->GetMap();
3260 uint32 pet_number = objmgr.GeneratePetNumber();
3261 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
3262 m_spellInfo->EffectMiscValue[i], pet_number))
3264 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3265 delete spawnCreature;
3266 return;
3269 // Summon in dest location
3270 float x,y,z;
3271 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3273 x = m_targets.m_destX;
3274 y = m_targets.m_destY;
3275 z = m_targets.m_destZ;
3277 else
3278 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3280 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3282 if(!spawnCreature->IsPositionValid())
3284 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3285 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3286 delete spawnCreature;
3287 return;
3290 // set timer for unsummon
3291 int32 duration = GetSpellDuration(m_spellInfo);
3292 if(duration > 0)
3293 spawnCreature->SetDuration(duration);
3295 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3296 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3297 spawnCreature->setPowerType(POWER_MANA);
3298 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3299 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3300 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3301 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3302 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3303 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3304 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3305 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3306 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3308 spawnCreature->InitStatsForLevel(level);
3310 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3312 spawnCreature->AIM_Initialize();
3313 spawnCreature->InitPetCreateSpells();
3314 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3315 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3317 std::string name = m_caster->GetName();
3318 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3319 spawnCreature->SetName( name );
3321 map->Add((Creature*)spawnCreature);
3323 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3325 m_caster->SetPet(spawnCreature);
3326 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3327 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3328 ((Player*)m_caster)->PetSpellInitialize();
3332 void Spell::EffectLearnSpell(uint32 i)
3334 if(!unitTarget)
3335 return;
3337 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3339 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3340 EffectLearnPetSpell(i);
3342 return;
3345 Player *player = (Player*)unitTarget;
3347 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3348 player->learnSpell(spellToLearn,false);
3350 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3353 void Spell::EffectDispel(uint32 i)
3355 if(!unitTarget)
3356 return;
3358 // Fill possible dispell list
3359 std::vector <Aura *> dispel_list;
3361 // Create dispel mask by dispel type
3362 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3363 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3364 Unit::AuraMap const& auras = unitTarget->GetAuras();
3365 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3367 Aura *aur = (*itr).second;
3368 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3370 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3372 bool positive = true;
3373 if (!aur->IsPositive())
3374 positive = false;
3375 else
3376 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3378 // do not remove positive auras if friendly target
3379 // negative auras if non-friendly target
3380 if(positive == unitTarget->IsFriendlyTo(m_caster))
3381 continue;
3383 // Add aura to dispel list
3384 dispel_list.push_back(aur);
3387 // Ok if exist some buffs for dispel try dispel it
3388 if (!dispel_list.empty())
3390 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3391 std::list < uint32 > fail_list; // spell_id
3392 int32 list_size = dispel_list.size();
3393 // Dispell N = damage buffs (or while exist buffs for dispel)
3394 for (int32 count=0; count < damage && list_size > 0; ++count)
3396 // Random select buff for dispel
3397 Aura *aur = dispel_list[urand(0, list_size-1)];
3399 SpellEntry const* spellInfo = aur->GetSpellProto();
3400 // Base dispel chance
3401 // TODO: possible chance depend from spell level??
3402 int32 miss_chance = 0;
3403 // Apply dispel mod from aura caster
3404 if (Unit *caster = aur->GetCaster())
3406 if ( Player* modOwner = caster->GetSpellModOwner() )
3407 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3409 // Try dispel
3410 if (roll_chance_i(miss_chance))
3411 fail_list.push_back(aur->GetId());
3412 else
3413 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3414 // Remove buff from list for prevent doubles
3415 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3417 Aura *dispeled = *j;
3418 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3420 j = dispel_list.erase(j);
3421 --list_size;
3423 else
3424 ++j;
3427 // Send success log and really remove auras
3428 if (!success_list.empty())
3430 int32 count = success_list.size();
3431 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3432 data.append(unitTarget->GetPackGUID()); // Victim GUID
3433 data.append(m_caster->GetPackGUID()); // Caster GUID
3434 data << uint32(m_spellInfo->Id); // Dispell spell id
3435 data << uint8(0); // not used
3436 data << uint32(count); // count
3437 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3439 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3440 data << uint32(spellInfo->Id); // Spell Id
3441 data << uint8(0); // 0 - dispeled !=0 cleansed
3442 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3444 m_caster->SendMessageToSet(&data, true);
3446 // On succes dispel
3447 // Devour Magic
3448 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3450 uint32 heal_spell = 0;
3451 switch (m_spellInfo->Id)
3453 case 19505: heal_spell = 19658; break;
3454 case 19731: heal_spell = 19732; break;
3455 case 19734: heal_spell = 19733; break;
3456 case 19736: heal_spell = 19735; break;
3457 case 27276: heal_spell = 27278; break;
3458 case 27277: heal_spell = 27279; break;
3459 default:
3460 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3461 break;
3463 if (heal_spell)
3464 m_caster->CastSpell(m_caster, heal_spell, true);
3467 // Send fail log to client
3468 if (!fail_list.empty())
3470 // Failed to dispell
3471 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3472 data << uint64(m_caster->GetGUID()); // Caster GUID
3473 data << uint64(unitTarget->GetGUID()); // Victim GUID
3474 data << uint32(m_spellInfo->Id); // Dispell spell id
3475 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3476 data << uint32(*j); // Spell Id
3477 m_caster->SendMessageToSet(&data, true);
3482 void Spell::EffectDualWield(uint32 /*i*/)
3484 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3485 ((Player*)unitTarget)->SetCanDualWield(true);
3488 void Spell::EffectPull(uint32 /*i*/)
3490 // TODO: create a proper pull towards distract spell center for distract
3491 sLog.outDebug("WORLD: Spell Effect DUMMY");
3494 void Spell::EffectDistract(uint32 /*i*/)
3496 // Check for possible target
3497 if (!unitTarget || unitTarget->isInCombat())
3498 return;
3500 // target must be OK to do this
3501 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3502 return;
3504 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3506 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3508 // For players just turn them
3509 WorldPacket data;
3510 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3511 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3512 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3514 else
3516 // Set creature Distracted, Stop it, And turn it
3517 unitTarget->SetOrientation(angle);
3518 unitTarget->StopMoving();
3519 unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3523 void Spell::EffectPickPocket(uint32 /*i*/)
3525 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3526 return;
3528 // victim must be creature and attackable
3529 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3530 return;
3532 // victim have to be alive and humanoid or undead
3533 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3535 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3537 if (chance > irand(0, 19))
3539 // Stealing successful
3540 //sLog.outDebug("Sending loot from pickpocket");
3541 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3543 else
3545 // Reveal action + get attack
3546 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3547 if (((Creature*)unitTarget)->AI())
3548 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3553 void Spell::EffectAddFarsight(uint32 i)
3555 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3556 int32 duration = GetSpellDuration(m_spellInfo);
3557 DynamicObject* dynObj = new DynamicObject;
3558 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3560 delete dynObj;
3561 return;
3563 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3564 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3565 m_caster->AddDynObject(dynObj);
3566 dynObj->GetMap()->Add(dynObj);
3567 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3568 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3571 void Spell::EffectSummonWild(uint32 i)
3573 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3574 if(!creature_entry)
3575 return;
3577 uint32 level = m_caster->getLevel();
3579 // level of creature summoned using engineering item based at engineering skill level
3580 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3582 ItemPrototype const *proto = m_CastItem->GetProto();
3583 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3585 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3586 if(skill202)
3588 level = skill202/5;
3593 // select center of summon position
3594 float center_x = m_targets.m_destX;
3595 float center_y = m_targets.m_destY;
3596 float center_z = m_targets.m_destZ;
3598 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3600 int32 amount = damage > 0 ? damage : 1;
3602 for(int32 count = 0; count < amount; ++count)
3604 float px, py, pz;
3605 // If dest location if present
3606 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3608 // Summon 1 unit in dest location
3609 if (count == 0)
3611 px = m_targets.m_destX;
3612 py = m_targets.m_destY;
3613 pz = m_targets.m_destZ;
3615 // Summon in random point all other units if location present
3616 else
3617 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3619 // Summon if dest location not present near caster
3620 else
3621 m_caster->GetClosePoint(px,py,pz,3.0f);
3623 int32 duration = GetSpellDuration(m_spellInfo);
3625 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3627 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3631 void Spell::EffectSummonGuardian(uint32 i)
3633 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3634 if(!pet_entry)
3635 return;
3637 // Jewelery statue case (totem like)
3638 if(m_spellInfo->SpellIconID==2056)
3640 EffectSummonTotem(i);
3641 return;
3644 // set timer for unsummon
3645 int32 duration = GetSpellDuration(m_spellInfo);
3647 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3648 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3649 // so this code hack in fact
3650 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3651 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3652 return; // find old guardian, ignore summon
3654 // in another case summon new
3655 uint32 level = m_caster->getLevel();
3657 // level of pet summoned using engineering item based at engineering skill level
3658 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3660 ItemPrototype const *proto = m_CastItem->GetProto();
3661 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3663 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3664 if(skill202)
3666 level = skill202/5;
3671 // select center of summon position
3672 float center_x = m_targets.m_destX;
3673 float center_y = m_targets.m_destY;
3674 float center_z = m_targets.m_destZ;
3676 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3678 int32 amount = damage > 0 ? damage : 1;
3680 for(int32 count = 0; count < amount; ++count)
3682 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3684 Map *map = m_caster->GetMap();
3685 uint32 pet_number = objmgr.GeneratePetNumber();
3686 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3687 m_spellInfo->EffectMiscValue[i], pet_number))
3689 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3690 delete spawnCreature;
3691 return;
3694 float px, py, pz;
3695 // If dest location if present
3696 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3698 // Summon 1 unit in dest location
3699 if (count == 0)
3701 px = m_targets.m_destX;
3702 py = m_targets.m_destY;
3703 pz = m_targets.m_destZ;
3705 // Summon in random point all other units if location present
3706 else
3707 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3709 // Summon if dest location not present near caster
3710 else
3711 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3713 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3715 if(!spawnCreature->IsPositionValid())
3717 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3718 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3719 delete spawnCreature;
3720 return;
3723 if(duration > 0)
3724 spawnCreature->SetDuration(duration);
3726 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3727 spawnCreature->setPowerType(POWER_MANA);
3728 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3729 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3730 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3731 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3732 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3733 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3734 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3736 spawnCreature->InitStatsForLevel(level);
3737 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3739 spawnCreature->AIM_Initialize();
3741 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3742 ((Player*)m_caster)->AddGuardian(spawnCreature);
3744 map->Add((Creature*)spawnCreature);
3748 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3750 if(!unitTarget)
3751 return;
3753 if(unitTarget->isInFlight())
3754 return;
3756 uint32 mapid = m_caster->GetMapId();
3757 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3759 float fx,fy,fz;
3760 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3762 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3763 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3764 else
3765 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3768 void Spell::EffectLearnSkill(uint32 i)
3770 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3771 return;
3773 if(damage < 0)
3774 return;
3776 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3777 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3778 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3781 void Spell::EffectAddHonor(uint32 /*i*/)
3783 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3784 return;
3786 sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3788 // TODO: find formula for honor reward based on player's level!
3790 // now fixed only for level 70 players:
3791 if (((Player*)unitTarget)->getLevel() == 70)
3792 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3795 void Spell::EffectTradeSkill(uint32 /*i*/)
3797 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3798 return;
3799 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3800 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3801 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3804 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3806 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3807 return;
3808 if (!itemTarget)
3809 return;
3811 Player* p_caster = (Player*)m_caster;
3813 // not grow at item use at item case
3814 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3816 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3817 if (!enchant_id)
3818 return;
3820 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3821 if(!pEnchant)
3822 return;
3824 // item can be in trade slot and have owner diff. from caster
3825 Player* item_owner = itemTarget->GetOwner();
3826 if(!item_owner)
3827 return;
3829 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3831 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3832 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3833 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3834 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3837 // remove old enchanting before applying new if equipped
3838 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3840 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3842 // add new enchanting if equipped
3843 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3846 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3848 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3849 return;
3850 if (!itemTarget)
3851 return;
3853 Player* p_caster = (Player*)m_caster;
3855 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3856 if (!enchant_id)
3857 return;
3859 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3860 if(!pEnchant)
3861 return;
3863 // support only enchantings with add socket in this slot
3865 bool add_socket = false;
3866 for(int i = 0; i < 3; ++i)
3868 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3870 add_socket = true;
3871 break;
3874 if(!add_socket)
3876 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.",
3877 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3878 return;
3882 // item can be in trade slot and have owner diff. from caster
3883 Player* item_owner = itemTarget->GetOwner();
3884 if(!item_owner)
3885 return;
3887 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3889 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3890 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3891 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3892 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3895 // remove old enchanting before applying new if equipped
3896 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3898 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3900 // add new enchanting if equipped
3901 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3904 void Spell::EffectEnchantItemTmp(uint32 i)
3906 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3907 return;
3909 Player* p_caster = (Player*)m_caster;
3911 if(!itemTarget)
3912 return;
3914 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3916 // Shaman Rockbiter Weapon
3917 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3919 int32 enchnting_damage = m_currentBasePoints[1]+1;
3921 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3922 // with already applied percent bonus from Elemental Weapons talent
3923 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3924 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3925 switch(enchnting_damage)
3927 // Rank 1
3928 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3929 // Rank 2
3930 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3931 case 5: enchant_id = 3025; break; // 20%
3932 // Rank 3
3933 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3934 case 7: enchant_id = 3027; break; // 20%
3935 // Rank 4
3936 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3937 case 10: enchant_id = 503; break; // 14%
3938 case 11: enchant_id = 3031; break; // 20%
3939 // Rank 5
3940 case 15: enchant_id = 3035; break; // 0%
3941 case 16: enchant_id = 1663; break; // 7%
3942 case 17: enchant_id = 3033; break; // 14%
3943 case 18: enchant_id = 3034; break; // 20%
3944 // Rank 6
3945 case 28: enchant_id = 3038; break; // 0%
3946 case 29: enchant_id = 683; break; // 7%
3947 case 31: enchant_id = 3036; break; // 14%
3948 case 33: enchant_id = 3037; break; // 20%
3949 // Rank 7
3950 case 40: enchant_id = 3041; break; // 0%
3951 case 42: enchant_id = 1664; break; // 7%
3952 case 45: enchant_id = 3039; break; // 14%
3953 case 48: enchant_id = 3040; break; // 20%
3954 // Rank 8
3955 case 49: enchant_id = 3044; break; // 0%
3956 case 52: enchant_id = 2632; break; // 7%
3957 case 55: enchant_id = 3042; break; // 14%
3958 case 58: enchant_id = 3043; break; // 20%
3959 // Rank 9
3960 case 62: enchant_id = 2633; break; // 0%
3961 case 66: enchant_id = 3018; break; // 7%
3962 case 70: enchant_id = 3019; break; // 14%
3963 case 74: enchant_id = 3020; break; // 20%
3964 default:
3965 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3966 return;
3970 if (!enchant_id)
3972 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3973 return;
3976 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3977 if(!pEnchant)
3979 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3980 return;
3983 // select enchantment duration
3984 uint32 duration;
3986 // rogue family enchantments exception by duration
3987 if(m_spellInfo->Id==38615)
3988 duration = 1800; // 30 mins
3989 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3990 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3991 duration = 3600; // 1 hour
3992 // shaman family enchantments
3993 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3994 duration = 1800; // 30 mins
3995 // other cases with this SpellVisual already selected
3996 else if(m_spellInfo->SpellVisual[0]==215)
3997 duration = 1800; // 30 mins
3998 // some fishing pole bonuses
3999 else if(m_spellInfo->SpellVisual[0]==563)
4000 duration = 600; // 10 mins
4001 // shaman rockbiter enchantments
4002 else if(m_spellInfo->SpellVisual[0]==0)
4003 duration = 1800; // 30 mins
4004 else if(m_spellInfo->Id==29702)
4005 duration = 300; // 5 mins
4006 else if(m_spellInfo->Id==37360)
4007 duration = 300; // 5 mins
4008 // default case
4009 else
4010 duration = 3600; // 1 hour
4012 // item can be in trade slot and have owner diff. from caster
4013 Player* item_owner = itemTarget->GetOwner();
4014 if(!item_owner)
4015 return;
4017 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4019 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4020 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4021 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4022 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4025 // remove old enchanting before applying new if equipped
4026 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
4028 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
4030 // add new enchanting if equipped
4031 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
4034 void Spell::EffectTameCreature(uint32 /*i*/)
4036 if(m_caster->GetPetGUID())
4037 return;
4039 if(!unitTarget)
4040 return;
4042 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4043 return;
4045 Creature* creatureTarget = (Creature*)unitTarget;
4047 if(creatureTarget->isPet())
4048 return;
4050 if(m_caster->getClass() != CLASS_HUNTER)
4051 return;
4053 // cast finish successfully
4054 //SendChannelUpdate(0);
4055 finish();
4057 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4059 // kill original creature
4060 creatureTarget->setDeathState(JUST_DIED);
4061 creatureTarget->RemoveCorpse();
4062 creatureTarget->SetHealth(0); // just for nice GM-mode view
4064 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4066 // prepare visual effect for levelup
4067 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4069 // add to world
4070 pet->GetMap()->Add((Creature*)pet);
4072 // visual effect for levelup
4073 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4075 // caster have pet now
4076 m_caster->SetPet(pet);
4078 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4080 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4081 ((Player*)m_caster)->PetSpellInitialize();
4085 void Spell::EffectSummonPet(uint32 i)
4087 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4089 Pet *OldSummon = m_caster->GetPet();
4091 // if pet requested type already exist
4092 if( OldSummon )
4094 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4096 // pet in corpse state can't be summoned
4097 if( OldSummon->isDead() )
4098 return;
4100 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4101 OldSummon->SetMapId(m_caster->GetMapId());
4103 float px, py, pz;
4104 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4106 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4107 m_caster->GetMap()->Add((Creature*)OldSummon);
4109 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4111 ((Player*)m_caster)->PetSpellInitialize();
4113 return;
4116 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4117 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4118 else
4119 return;
4122 Pet* NewSummon = new Pet;
4124 // petentry==0 for hunter "call pet" (current pet summoned if any)
4125 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4127 if(NewSummon->getPetType()==SUMMON_PET)
4129 // Remove Demonic Sacrifice auras (known pet)
4130 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4131 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4133 if((*itr)->GetModifier()->m_miscvalue==2228)
4135 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4136 itr = auraClassScripts.begin();
4138 else
4139 ++itr;
4143 return;
4146 // not error in case fail hunter call pet
4147 if(!petentry)
4149 delete NewSummon;
4150 return;
4153 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4155 if(!cInfo)
4157 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4158 delete NewSummon;
4159 return;
4162 Map *map = m_caster->GetMap();
4163 uint32 pet_number = objmgr.GeneratePetNumber();
4164 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4165 petentry, pet_number))
4167 delete NewSummon;
4168 return;
4171 float px, py, pz;
4172 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4174 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4176 if(!NewSummon->IsPositionValid())
4178 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4179 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4180 delete NewSummon;
4181 return;
4184 uint32 petlevel = m_caster->getLevel();
4185 NewSummon->setPetType(SUMMON_PET);
4187 uint32 faction = m_caster->getFaction();
4188 if(m_caster->GetTypeId() == TYPEID_UNIT)
4190 if ( ((Creature*)m_caster)->isTotem() )
4191 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4192 else
4193 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4196 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4197 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4198 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4199 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4200 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4201 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4202 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4203 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4204 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4205 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4207 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4208 // this enables pet details window (Shift+P)
4210 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4211 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4212 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4214 NewSummon->InitStatsForLevel(petlevel);
4215 NewSummon->InitPetCreateSpells();
4216 NewSummon->InitTalentForLevel();
4218 if(NewSummon->getPetType()==SUMMON_PET)
4220 // Remove Demonic Sacrifice auras (new pet)
4221 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4222 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4224 if((*itr)->GetModifier()->m_miscvalue==2228)
4226 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4227 itr = auraClassScripts.begin();
4229 else
4230 ++itr;
4233 // generate new name for summon pet
4234 std::string new_name=objmgr.GeneratePetName(petentry);
4235 if(!new_name.empty())
4236 NewSummon->SetName(new_name);
4238 else if(NewSummon->getPetType()==HUNTER_PET)
4239 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4241 NewSummon->AIM_Initialize();
4242 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4243 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4245 map->Add((Creature*)NewSummon);
4247 m_caster->SetPet(NewSummon);
4248 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4250 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4252 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4253 ((Player*)m_caster)->PetSpellInitialize();
4257 void Spell::EffectLearnPetSpell(uint32 i)
4259 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4260 return;
4262 Player *_player = (Player*)m_caster;
4264 Pet *pet = _player->GetPet();
4265 if(!pet)
4266 return;
4267 if(!pet->isAlive())
4268 return;
4270 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4271 if(!learn_spellproto)
4272 return;
4274 pet->learnSpell(learn_spellproto->Id);
4276 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4277 _player->PetSpellInitialize();
4280 void Spell::EffectTaunt(uint32 /*i*/)
4282 // this effect use before aura Taunt apply for prevent taunt already attacking target
4283 // for spell as marked "non effective at already attacking target"
4284 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4286 if(unitTarget->getVictim()==m_caster)
4288 SendCastResult(SPELL_FAILED_DONT_REPORT);
4289 return;
4293 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4294 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4295 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4298 void Spell::EffectWeaponDmg(uint32 i)
4300 if(!unitTarget)
4301 return;
4302 if(!unitTarget->isAlive())
4303 return;
4305 // multiple weapon dmg effect workaround
4306 // execute only the last weapon damage
4307 // and handle all effects at once
4308 for (int j = 0; j < 3; j++)
4310 switch(m_spellInfo->Effect[j])
4312 case SPELL_EFFECT_WEAPON_DAMAGE:
4313 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4314 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4315 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4316 if (j < i) // we must calculate only at last weapon effect
4317 return;
4318 break;
4322 // some spell specific modifiers
4323 bool customBonusDamagePercentMod = false;
4324 float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4325 float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4326 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4327 bool normalized = false;
4329 int32 spell_bonus = 0; // bonus specific for spell
4330 switch(m_spellInfo->SpellFamilyName)
4332 case SPELLFAMILY_WARRIOR:
4334 // Whirlwind, single only spell with 2 weapon white damage apply if have
4335 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4337 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4338 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4340 // Devastate bonus and sunder armor refresh
4341 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4343 uint32 stack = 0;
4344 // Need refresh all Sunder Armor auras from this caster
4345 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4346 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4348 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4349 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4350 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4351 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4353 (*itr).second->RefreshAura();
4354 stack = (*itr).second->GetStackAmount();
4357 if (stack)
4358 spell_bonus += stack * CalculateDamage(2, unitTarget);
4360 break;
4362 case SPELLFAMILY_ROGUE:
4364 // Ambush
4365 if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4367 customBonusDamagePercentMod = true;
4368 bonusDamagePercentMod = 2.5f; // 250%
4370 // Mutilate (for each hand)
4371 else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4373 bool found = false;
4374 // fast check
4375 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4376 found = true;
4377 // full aura scan
4378 else
4380 Unit::AuraMap const& auras = unitTarget->GetAuras();
4381 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4383 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4385 found = true;
4386 break;
4391 if(found)
4392 totalDamagePercentMod *= 1.5f; // 150% if poisoned
4394 break;
4396 case SPELLFAMILY_PALADIN:
4398 // Seal of Command - receive benefit from Spell Damage and Healing
4399 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4401 spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4402 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4404 break;
4406 case SPELLFAMILY_SHAMAN:
4408 // Skyshatter Harness item set bonus
4409 // Stormstrike
4410 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4412 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4413 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4415 // Stormstrike AP Buff
4416 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4418 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4419 break;
4426 int32 fixed_bonus = 0;
4427 for (int j = 0; j < 3; j++)
4429 switch(m_spellInfo->Effect[j])
4431 case SPELL_EFFECT_WEAPON_DAMAGE:
4432 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4433 fixed_bonus += CalculateDamage(j,unitTarget);
4434 break;
4435 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4436 fixed_bonus += CalculateDamage(j,unitTarget);
4437 normalized = true;
4438 break;
4439 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4440 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4442 // applied only to prev.effects fixed damage
4443 if(customBonusDamagePercentMod)
4444 fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4445 else
4446 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4447 break;
4448 default:
4449 break; // not weapon damage effect, just skip
4453 // non-weapon damage
4454 int32 bonus = spell_bonus + fixed_bonus;
4456 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4457 if(bonus)
4459 UnitMods unitMod;
4460 switch(m_attackType)
4462 default:
4463 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4464 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4465 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4468 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4469 bonus = int32(bonus*weapon_total_pct);
4472 // + weapon damage with applied weapon% dmg to base weapon damage in call
4473 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4475 // total damage
4476 bonus = int32(bonus*totalDamagePercentMod);
4478 // prevent negative damage
4479 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4481 // Add melee damage bonuses (also check for negative)
4482 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4483 m_damage+= eff_damage;
4485 // Hemorrhage
4486 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4488 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4489 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4492 // Mangle (Cat): CP
4493 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4495 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4496 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4499 // take ammo
4500 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4502 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4504 // wands don't have ammo
4505 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4506 return;
4508 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4510 if(pItem->GetMaxStackCount()==1)
4512 // decrease durability for non-stackable throw weapon
4513 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4515 else
4517 // decrease items amount for stackable throw weapon
4518 uint32 count = 1;
4519 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4522 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4523 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4527 void Spell::EffectThreat(uint32 /*i*/)
4529 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4530 return;
4532 if(!unitTarget->CanHaveThreatList())
4533 return;
4535 unitTarget->AddThreat(m_caster, float(damage));
4538 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4540 if(!unitTarget)
4541 return;
4542 if(!unitTarget->isAlive())
4543 return;
4545 uint32 heal = m_caster->GetMaxHealth();
4547 m_healing+=heal;
4550 void Spell::EffectInterruptCast(uint32 /*i*/)
4552 if(!unitTarget)
4553 return;
4554 if(!unitTarget->isAlive())
4555 return;
4557 // TODO: not all spells that used this effect apply cooldown at school spells
4558 // also exist case: apply cooldown to interrupted cast only and to all spells
4559 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4561 if (unitTarget->m_currentSpells[i])
4563 // check if we can interrupt spell
4564 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4566 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4567 unitTarget->InterruptSpell(i,false);
4573 void Spell::EffectSummonObjectWild(uint32 i)
4575 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4577 GameObject* pGameObj = new GameObject;
4579 WorldObject* target = focusObject;
4580 if( !target )
4581 target = m_caster;
4583 float x,y,z;
4584 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4586 x = m_targets.m_destX;
4587 y = m_targets.m_destY;
4588 z = m_targets.m_destZ;
4590 else
4591 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4593 Map *map = target->GetMap();
4595 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4596 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4598 delete pGameObj;
4599 return;
4602 int32 duration = GetSpellDuration(m_spellInfo);
4603 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4604 pGameObj->SetSpellId(m_spellInfo->Id);
4606 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4607 m_caster->AddGameObject(pGameObj);
4608 map->Add(pGameObj);
4610 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4612 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4614 Player *pl = (Player*)m_caster;
4615 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4616 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4618 uint32 team = ALLIANCE;
4620 if(pl->GetTeam() == team)
4621 team = HORDE;
4623 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4628 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4630 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4632 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4633 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4635 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4640 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4642 GameObject* linkedGO = new GameObject;
4643 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4644 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4646 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4647 linkedGO->SetSpellId(m_spellInfo->Id);
4649 m_caster->AddGameObject(linkedGO);
4650 map->Add(linkedGO);
4652 else
4654 delete linkedGO;
4655 linkedGO = NULL;
4656 return;
4661 void Spell::EffectScriptEffect(uint32 effIndex)
4663 // TODO: we must implement hunter pet summon at login there (spell 6962)
4665 switch(m_spellInfo->SpellFamilyName)
4667 case SPELLFAMILY_GENERIC:
4669 switch(m_spellInfo->Id)
4671 // PX-238 Winter Wondervolt TRAP
4672 case 26275:
4674 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4676 // check presence
4677 for(int j = 0; j < 4; ++j)
4678 if(unitTarget->HasAura(spells[j],0))
4679 return;
4681 // select spell
4682 uint32 iTmpSpellId = spells[urand(0,3)];
4684 // cast
4685 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4686 return;
4688 // Bending Shinbone
4689 case 8856:
4691 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4692 return;
4694 uint32 spell_id = 0;
4695 switch(urand(1,5))
4697 case 1: spell_id = 8854; break;
4698 default: spell_id = 8855; break;
4701 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4702 return;
4704 // Brittle Armor - need remove one 24575 Brittle Armor aura
4705 case 24590:
4706 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4707 return;
4708 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4709 case 26465:
4710 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4711 return;
4712 // Orb teleport spells
4713 case 25140:
4714 case 25143:
4715 case 25650:
4716 case 25652:
4717 case 29128:
4718 case 29129:
4719 case 35376:
4720 case 35727:
4722 if(!unitTarget)
4723 return;
4725 uint32 spellid;
4726 switch(m_spellInfo->Id)
4728 case 25140: spellid = 32571; break;
4729 case 25143: spellid = 32572; break;
4730 case 25650: spellid = 30140; break;
4731 case 25652: spellid = 30141; break;
4732 case 29128: spellid = 32568; break;
4733 case 29129: spellid = 32569; break;
4734 case 35376: spellid = 25649; break;
4735 case 35727: spellid = 35730; break;
4736 default:
4737 return;
4740 unitTarget->CastSpell(unitTarget,spellid,false);
4741 return;
4743 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4744 case 22539:
4745 case 22972:
4746 case 22975:
4747 case 22976:
4748 case 22977:
4749 case 22978:
4750 case 22979:
4751 case 22980:
4752 case 22981:
4753 case 22982:
4754 case 22983:
4755 case 22984:
4756 case 22985:
4758 if(!unitTarget || !unitTarget->isAlive())
4759 return;
4761 // Onyxia Scale Cloak
4762 if(unitTarget->GetDummyAura(22683))
4763 return;
4765 // Shadow Flame
4766 m_caster->CastSpell(unitTarget, 22682, true);
4767 return;
4769 // Summon Black Qiraji Battle Tank
4770 case 26656:
4772 if(!unitTarget)
4773 return;
4775 // Prevent stacking of mounts
4776 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4778 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4779 if (unitTarget->GetAreaId() == 3428)
4780 unitTarget->CastSpell(unitTarget, 25863, false);
4781 else
4782 unitTarget->CastSpell(unitTarget, 26655, false);
4783 break;
4785 // Piccolo of the Flaming Fire
4786 case 17512:
4788 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4789 return;
4790 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4791 break;
4793 // Mirren's Drinking Hat
4794 case 29830:
4796 uint32 item = 0;
4797 switch ( urand(1,6) )
4799 case 1:case 2:case 3:
4800 item = 23584;break; // Loch Modan Lager
4801 case 4:case 5:
4802 item = 23585;break; // Stouthammer Lite
4803 case 6:
4804 item = 23586;break; // Aerie Peak Pale Ale
4806 if (item)
4807 DoCreateItem(effIndex,item);
4808 break;
4810 // Improved Sprint
4811 case 30918:
4813 // Removes snares and roots.
4814 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4815 Unit::AuraMap& Auras = unitTarget->GetAuras();
4816 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4818 next = iter;
4819 ++next;
4820 Aura *aur = iter->second;
4821 if (!aur->IsPositive()) //only remove negative spells
4823 // check for mechanic mask
4824 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4826 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4827 if(Auras.empty())
4828 break;
4829 else
4830 next = Auras.begin();
4834 break;
4836 // Flame Crash
4837 case 41126:
4839 if(!unitTarget)
4840 return;
4842 unitTarget->CastSpell(unitTarget, 41131, true);
4843 break;
4845 // Force Cast - Portal Effect: Sunwell Isle
4846 case 44876:
4848 if(!unitTarget)
4849 return;
4851 unitTarget->CastSpell(unitTarget, 44870, true);
4852 break;
4854 // Goblin Weather Machine
4855 case 46203:
4857 if(!unitTarget)
4858 return;
4860 uint32 spellId;
4861 switch(rand()%4)
4863 case 0: spellId = 46740; break;
4864 case 1: spellId = 46739; break;
4865 case 2: spellId = 46738; break;
4866 case 3: spellId = 46736; break;
4868 unitTarget->CastSpell(unitTarget, spellId, true);
4869 break;
4871 //5,000 Gold
4872 case 46642:
4874 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4875 return;
4877 ((Player*)unitTarget)->ModifyMoney(50000000);
4879 break;
4881 // Emblazon Runeblade
4882 case 51770:
4884 if(!unitTarget)
4885 return;
4887 unitTarget->CastSpell(unitTarget,51771,false);
4888 break;
4890 // Death Gate
4891 case 52751:
4893 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4894 return;
4895 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4896 unitTarget->CastSpell(unitTarget, damage, false);
4897 break;
4899 // random spell learn instead placeholder
4900 case 60893: // Northrend Alchemy Research
4901 case 61177: // Northrend Inscription Research
4902 case 61288: // Minor Inscription Research
4903 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4905 if(!IsExplicitDiscoverySpell(m_spellInfo))
4907 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4908 return;
4911 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4912 return;
4913 Player* player = (Player*)m_caster;
4915 // need replace effect 0 item by loot
4916 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4918 if(!player->HasItemCount(reagent_id,1))
4919 return;
4921 // remove reagent
4922 uint32 count = 1;
4923 player->DestroyItemCount (reagent_id,count,true);
4925 // create some random items
4926 player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
4928 // learn random explicit discovery recipe (if any)
4929 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4930 player->learnSpell(discoveredSpell,false);
4931 return;
4934 break;
4936 case SPELLFAMILY_WARLOCK:
4938 switch(m_spellInfo->Id)
4940 // Healthstone creating spells
4941 case 6201:
4942 case 6202:
4943 case 5699:
4944 case 11729:
4945 case 11730:
4946 case 27230:
4947 case 47871:
4948 case 47878:
4950 uint32 itemtype;
4951 uint32 rank = 0;
4952 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4953 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4955 if((*i)->GetId() == 18692)
4957 rank = 1;
4958 break;
4960 else if((*i)->GetId() == 18693)
4962 rank = 2;
4963 break;
4967 static uint32 const itypes[8][3] = {
4968 { 5512,19004,19005}, // Minor Healthstone
4969 { 5511,19006,19007}, // Lesser Healthstone
4970 { 5509,19008,19009}, // Healthstone
4971 { 5510,19010,19011}, // Greater Healthstone
4972 { 9421,19012,19013}, // Major Healthstone
4973 {22103,22104,22105}, // Master Healthstone
4974 {36889,36890,36891}, // Demonic Healthstone
4975 {36892,36893,36894} // Fel Healthstone
4978 switch(m_spellInfo->Id)
4980 case 6201:
4981 itemtype=itypes[0][rank];break; // Minor Healthstone
4982 case 6202:
4983 itemtype=itypes[1][rank];break; // Lesser Healthstone
4984 case 5699:
4985 itemtype=itypes[2][rank];break; // Healthstone
4986 case 11729:
4987 itemtype=itypes[3][rank];break; // Greater Healthstone
4988 case 11730:
4989 itemtype=itypes[4][rank];break; // Major Healthstone
4990 case 27230:
4991 itemtype=itypes[5][rank];break; // Master Healthstone
4992 case 47871:
4993 itemtype=itypes[6][rank];break; // Demonic Healthstone
4994 case 47878:
4995 itemtype=itypes[7][rank];break; // Fel Healthstone
4996 default:
4997 return;
4999 DoCreateItem( effIndex, itemtype );
5000 return;
5003 break;
5005 case SPELLFAMILY_PRIEST:
5007 switch(m_spellInfo->Id)
5009 // Pain and Suffering
5010 case 47948:
5012 if (!unitTarget)
5013 return;
5014 // Refresh Shadow Word: Pain on target
5015 Unit::AuraMap& auras = unitTarget->GetAuras();
5016 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5018 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5019 if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5020 spellInfo->SpellFamilyFlags & 0x0000000000008000LL &&
5021 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5023 (*itr).second->RefreshAura();
5024 return;
5027 return;
5029 default:
5030 break;
5032 break;
5034 case SPELLFAMILY_HUNTER:
5036 switch(m_spellInfo->Id)
5038 // Chimera Shot
5039 case 53209:
5041 uint32 spellId = 0;
5042 int32 basePoint = 0;
5043 Unit::AuraMap& Auras = unitTarget->GetAuras();
5044 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5046 Aura *aura = (*i).second;
5047 if (aura->GetCasterGUID() != m_caster->GetGUID())
5048 continue;
5049 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5050 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5051 if (!(familyFlag & 0x000000800000C000LL))
5052 continue;
5053 // Refresh aura duration
5054 aura->RefreshAura();
5056 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5057 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
5059 spellId = 53353; // 53353 Chimera Shot - Serpent
5060 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5062 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5063 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
5065 spellId = 53358; // 53358 Chimera Shot - Viper
5066 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5068 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5069 if (familyFlag & 0x0000000000008000LL)
5070 spellId = 53359; // 53359 Chimera Shot - Scorpid
5071 // ?? nothing say in spell desc (possibly need addition check)
5072 //if (familyFlag & 0x0000010000000000LL || // dot
5073 // familyFlag & 0x0000100000000000LL) // stun
5075 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5078 if (spellId)
5079 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5080 return;
5082 default:
5083 break;
5085 break;
5087 case SPELLFAMILY_PALADIN:
5089 // Judgement
5090 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
5092 if(!unitTarget || !unitTarget->isAlive())
5093 return;
5094 uint32 spellId1 = 0;
5095 uint32 spellId2 = 0;
5097 // Judgement self add switch
5098 switch (m_spellInfo->Id)
5100 case 41467: break; // Judgement
5101 case 53407: spellId1 = 20184; break; // Judgement of Justice
5102 case 20271: // Judgement of Light
5103 case 57774: spellId1 = 20185; break; // Judgement of Light
5104 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5105 default:
5106 return;
5108 // all seals have aura dummy in 2 effect
5109 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5110 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5112 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5113 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5114 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5115 continue;
5116 spellId2 = (*itr)->GetModifier()->m_amount;
5117 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5118 if (!judge)
5119 continue;
5120 break;
5122 if (spellId1)
5123 m_caster->CastSpell(unitTarget, spellId1, true);
5124 if (spellId2)
5125 m_caster->CastSpell(unitTarget, spellId2, true);
5126 return;
5129 case SPELLFAMILY_POTION:
5131 switch(m_spellInfo->Id)
5133 // Dreaming Glory
5134 case 28698:
5136 if(!unitTarget)
5137 return;
5138 unitTarget->CastSpell(unitTarget, 28694, true);
5139 break;
5141 // Netherbloom
5142 case 28702:
5144 if(!unitTarget)
5145 return;
5146 // 25% chance of casting a random buff
5147 if(roll_chance_i(75))
5148 return;
5150 // triggered spells are 28703 to 28707
5151 // Note: some sources say, that there was the possibility of
5152 // receiving a debuff. However, this seems to be removed by a patch.
5153 const uint32 spellid = 28703;
5155 // don't overwrite an existing aura
5156 for(uint8 i=0; i<5; i++)
5157 if(unitTarget->HasAura(spellid+i, 0))
5158 return;
5159 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5160 break;
5163 // Nightmare Vine
5164 case 28720:
5166 if(!unitTarget)
5167 return;
5168 // 25% chance of casting Nightmare Pollen
5169 if(roll_chance_i(75))
5170 return;
5171 unitTarget->CastSpell(unitTarget, 28721, true);
5172 break;
5175 break;
5179 // normal DB scripted effect
5180 if(!unitTarget)
5181 return;
5183 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5184 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5187 void Spell::EffectSanctuary(uint32 /*i*/)
5189 if(!unitTarget)
5190 return;
5191 //unitTarget->CombatStop();
5193 unitTarget->CombatStop();
5194 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5195 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5196 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5198 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5202 void Spell::EffectAddComboPoints(uint32 /*i*/)
5204 if(!unitTarget)
5205 return;
5207 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5208 return;
5210 if(damage <= 0)
5211 return;
5213 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5216 void Spell::EffectDuel(uint32 i)
5218 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5219 return;
5221 Player *caster = (Player*)m_caster;
5222 Player *target = (Player*)unitTarget;
5224 // caster or target already have requested duel
5225 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5226 return;
5228 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5229 // Don't have to check the target's map since you cannot challenge someone across maps
5230 uint32 mapid = caster->GetMapId();
5231 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5233 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5234 return;
5237 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5238 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5240 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5241 return;
5244 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5245 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5247 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5248 return;
5251 //CREATE DUEL FLAG OBJECT
5252 GameObject* pGameObj = new GameObject;
5254 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5256 Map *map = m_caster->GetMap();
5257 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5258 map, m_caster->GetPhaseMask(),
5259 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5260 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5261 m_caster->GetPositionZ(),
5262 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5264 delete pGameObj;
5265 return;
5268 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5269 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5270 int32 duration = GetSpellDuration(m_spellInfo);
5271 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5272 pGameObj->SetSpellId(m_spellInfo->Id);
5274 m_caster->AddGameObject(pGameObj);
5275 map->Add(pGameObj);
5276 //END
5278 // Send request
5279 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5280 data << pGameObj->GetGUID();
5281 data << caster->GetGUID();
5282 caster->GetSession()->SendPacket(&data);
5283 target->GetSession()->SendPacket(&data);
5285 // create duel-info
5286 DuelInfo *duel = new DuelInfo;
5287 duel->initiator = caster;
5288 duel->opponent = target;
5289 duel->startTime = 0;
5290 duel->startTimer = 0;
5291 caster->duel = duel;
5293 DuelInfo *duel2 = new DuelInfo;
5294 duel2->initiator = caster;
5295 duel2->opponent = caster;
5296 duel2->startTime = 0;
5297 duel2->startTimer = 0;
5298 target->duel = duel2;
5300 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5301 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5304 void Spell::EffectStuck(uint32 /*i*/)
5306 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5307 return;
5309 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5310 return;
5312 Player* pTarget = (Player*)unitTarget;
5314 sLog.outDebug("Spell Effect: Stuck");
5315 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());
5317 if(pTarget->isInFlight())
5318 return;
5320 // homebind location is loaded always
5321 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5323 // Stuck spell trigger Hearthstone cooldown
5324 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5325 if(!spellInfo)
5326 return;
5327 Spell spell(pTarget,spellInfo,true,0);
5328 spell.SendSpellCooldown();
5331 void Spell::EffectSummonPlayer(uint32 /*i*/)
5333 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5334 return;
5336 // Evil Twin (ignore player summon, but hide this for summoner)
5337 if(unitTarget->GetDummyAura(23445))
5338 return;
5340 float x,y,z;
5341 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5343 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5345 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5346 data << uint64(m_caster->GetGUID()); // summoner guid
5347 data << uint32(m_caster->GetZoneId()); // summoner zone
5348 data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs
5349 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5352 static ScriptInfo generateActivateCommand()
5354 ScriptInfo si;
5355 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5356 return si;
5359 void Spell::EffectActivateObject(uint32 effect_idx)
5361 if(!gameObjTarget)
5362 return;
5364 static ScriptInfo activateCommand = generateActivateCommand();
5366 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5368 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5371 void Spell::EffectApplyGlyph(uint32 i)
5373 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5374 return;
5376 Player *player = (Player*)m_caster;
5378 // remove old glyph
5379 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5381 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5383 player->RemoveAurasDueToSpell(old_gp->SpellId);
5384 player->SetGlyph(m_glyphIndex, 0);
5388 // apply new one
5389 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5391 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5393 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5395 if(gp->TypeFlags != gs->TypeFlags)
5397 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5398 return; // glyph slot missmatch
5402 player->CastSpell(m_caster, gp->SpellId, true);
5403 player->SetGlyph(m_glyphIndex, glyph);
5408 void Spell::EffectSummonTotem(uint32 i)
5410 uint8 slot = 0;
5411 switch(m_spellInfo->EffectMiscValueB[i])
5413 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5414 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5415 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5416 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5417 // Battle standard case
5418 case SUMMON_TYPE_TOTEM: slot = 254; break;
5419 // jewelery statue case, like totem without slot
5420 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5421 default: return;
5424 if(slot < MAX_TOTEM)
5426 uint64 guid = m_caster->m_TotemSlot[slot];
5427 if(guid != 0)
5429 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5430 if(OldTotem && OldTotem->isTotem())
5431 ((Totem*)OldTotem)->UnSummon();
5435 uint32 team = 0;
5436 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5437 team = ((Player*)m_caster)->GetTeam();
5439 Totem* pTotem = new Totem;
5441 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5442 m_spellInfo->EffectMiscValue[i], team ))
5444 delete pTotem;
5445 return;
5448 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5450 float x,y,z;
5451 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5453 // totem must be at same Z in case swimming caster and etc.
5454 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5455 z = m_caster->GetPositionZ();
5457 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5459 if(slot < MAX_TOTEM)
5460 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5462 pTotem->SetOwner(m_caster->GetGUID());
5463 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5465 int32 duration=GetSpellDuration(m_spellInfo);
5466 if(Player* modOwner = m_caster->GetSpellModOwner())
5467 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5468 pTotem->SetDuration(duration);
5470 if (damage) // if not spell info, DB values used
5472 pTotem->SetMaxHealth(damage);
5473 pTotem->SetHealth(damage);
5476 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5478 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5479 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5481 pTotem->Summon(m_caster);
5483 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5485 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5486 data << uint8(slot);
5487 data << uint64(pTotem->GetGUID());
5488 data << uint32(duration);
5489 data << uint32(m_spellInfo->Id);
5490 ((Player*)m_caster)->SendDirectMessage(&data);
5494 void Spell::EffectEnchantHeldItem(uint32 i)
5496 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5497 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5498 return;
5500 Player* item_owner = (Player*)unitTarget;
5501 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5503 if(!item )
5504 return;
5506 // must be equipped
5507 if(!item ->IsEquipped())
5508 return;
5510 if (m_spellInfo->EffectMiscValue[i])
5512 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5513 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5514 if(!duration)
5515 duration = m_currentBasePoints[i]+1; //Base points after ..
5516 if(!duration)
5517 duration = 10; //10 seconds for enchants which don't have listed duration
5519 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5520 if(!pEnchant)
5521 return;
5523 // Always go to temp enchantment slot
5524 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5526 // Enchantment will not be applied if a different one already exists
5527 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5528 return;
5530 // Apply the temporary enchantment
5531 item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5532 item_owner->ApplyEnchantment(item,slot,true);
5536 void Spell::EffectDisEnchant(uint32 /*i*/)
5538 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5539 return;
5541 Player* p_caster = (Player*)m_caster;
5542 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5543 return;
5545 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5547 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5549 // item will be removed at disenchanting end
5552 void Spell::EffectInebriate(uint32 /*i*/)
5554 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5555 return;
5557 Player *player = (Player*)unitTarget;
5558 uint16 currentDrunk = player->GetDrunkValue();
5559 uint16 drunkMod = damage * 256;
5560 if (currentDrunk + drunkMod > 0xFFFF)
5561 currentDrunk = 0xFFFF;
5562 else
5563 currentDrunk += drunkMod;
5564 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5567 void Spell::EffectFeedPet(uint32 i)
5569 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5570 return;
5572 Player *_player = (Player*)m_caster;
5574 Item* foodItem = m_targets.getItemTarget();
5575 if(!foodItem)
5576 return;
5578 Pet *pet = _player->GetPet();
5579 if(!pet)
5580 return;
5582 if(!pet->isAlive())
5583 return;
5585 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5586 if(benefit <= 0)
5587 return;
5589 uint32 count = 1;
5590 _player->DestroyItemCount(foodItem,count,true);
5591 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5593 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5596 void Spell::EffectDismissPet(uint32 /*i*/)
5598 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5599 return;
5601 Pet* pet = m_caster->GetPet();
5603 // not let dismiss dead pet
5604 if(!pet||!pet->isAlive())
5605 return;
5607 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5610 void Spell::EffectSummonObject(uint32 i)
5612 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5614 uint8 slot = 0;
5615 switch(m_spellInfo->Effect[i])
5617 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5618 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5619 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5620 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5621 default: return;
5624 uint64 guid = m_caster->m_ObjectSlot[slot];
5625 if(guid != 0)
5627 GameObject* obj = NULL;
5628 if( m_caster )
5629 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5631 if(obj) obj->Delete();
5632 m_caster->m_ObjectSlot[slot] = 0;
5635 GameObject* pGameObj = new GameObject;
5637 float rot2 = sin(m_caster->GetOrientation()/2);
5638 float rot3 = cos(m_caster->GetOrientation()/2);
5640 float x,y,z;
5641 // If dest location if present
5642 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5644 x = m_targets.m_destX;
5645 y = m_targets.m_destY;
5646 z = m_targets.m_destZ;
5648 // Summon in random point all other units if location present
5649 else
5650 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5652 Map *map = m_caster->GetMap();
5653 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5654 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5656 delete pGameObj;
5657 return;
5660 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5661 int32 duration = GetSpellDuration(m_spellInfo);
5662 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5663 pGameObj->SetSpellId(m_spellInfo->Id);
5664 m_caster->AddGameObject(pGameObj);
5666 map->Add(pGameObj);
5667 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5668 data << pGameObj->GetGUID();
5669 m_caster->SendMessageToSet(&data,true);
5671 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5674 void Spell::EffectResurrect(uint32 /*effIndex*/)
5676 if(!unitTarget)
5677 return;
5678 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5679 return;
5681 if(unitTarget->isAlive())
5682 return;
5683 if(!unitTarget->IsInWorld())
5684 return;
5686 switch (m_spellInfo->Id)
5688 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5689 case 8342:
5690 if (roll_chance_i(67))
5692 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5693 return;
5695 break;
5696 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5697 case 22999:
5698 if (roll_chance_i(50))
5700 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5701 return;
5703 break;
5704 default:
5705 break;
5708 Player* pTarget = ((Player*)unitTarget);
5710 if(pTarget->isRessurectRequested()) // already have one active request
5711 return;
5713 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5714 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5716 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5717 SendResurrectRequest(pTarget);
5720 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5722 if(!unitTarget || !unitTarget->isAlive())
5723 return;
5725 if( unitTarget->m_extraAttacks )
5726 return;
5728 unitTarget->m_extraAttacks = damage;
5731 void Spell::EffectParry(uint32 /*i*/)
5733 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5734 ((Player*)unitTarget)->SetCanParry(true);
5737 void Spell::EffectBlock(uint32 /*i*/)
5739 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5740 ((Player*)unitTarget)->SetCanBlock(true);
5743 void Spell::EffectMomentMove(uint32 i)
5745 if(unitTarget->isInFlight())
5746 return;
5748 if( m_spellInfo->rangeIndex== 1) //self range
5750 uint32 mapid = m_caster->GetMapId();
5751 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5753 // before caster
5754 float fx,fy,fz;
5755 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5756 float ox,oy,oz;
5757 unitTarget->GetPosition(ox,oy,oz);
5759 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5760 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5762 fx = fx2;
5763 fy = fy2;
5764 fz = fz2;
5765 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5768 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5769 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5770 else
5771 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5775 void Spell::EffectReputation(uint32 i)
5777 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5778 return;
5780 Player *_player = (Player*)unitTarget;
5782 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5784 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5786 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5788 if(!factionEntry)
5789 return;
5791 _player->ModifyFactionReputation(factionEntry,rep_change);
5794 void Spell::EffectQuestComplete(uint32 i)
5796 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5797 return;
5799 Player *_player = (Player*)m_caster;
5801 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5802 _player->AreaExploredOrEventHappens(quest_id);
5805 void Spell::EffectSelfResurrect(uint32 i)
5807 if(!unitTarget || unitTarget->isAlive())
5808 return;
5809 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5810 return;
5811 if(!unitTarget->IsInWorld())
5812 return;
5814 uint32 health = 0;
5815 uint32 mana = 0;
5817 // flat case
5818 if(damage < 0)
5820 health = uint32(-damage);
5821 mana = m_spellInfo->EffectMiscValue[i];
5823 // percent case
5824 else
5826 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5827 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5828 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5831 Player *plr = ((Player*)unitTarget);
5832 plr->ResurrectPlayer(0.0f);
5834 plr->SetHealth( health );
5835 plr->SetPower(POWER_MANA, mana );
5836 plr->SetPower(POWER_RAGE, 0 );
5837 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5839 plr->SpawnCorpseBones();
5841 plr->SaveToDB();
5844 void Spell::EffectSkinning(uint32 /*i*/)
5846 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5847 return;
5848 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5849 return;
5851 Creature* creature = (Creature*) unitTarget;
5852 int32 targetLevel = creature->getLevel();
5854 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5856 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5857 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5859 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5861 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5863 // Double chances for elites
5864 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5867 void Spell::EffectCharge(uint32 /*i*/)
5869 if(!unitTarget || !m_caster)
5870 return;
5872 float x, y, z;
5873 unitTarget->GetContactPoint(m_caster, x, y, z);
5874 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5875 ((Creature *)unitTarget)->StopMoving();
5877 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5878 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5880 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5881 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5883 // not all charge effects used in negative spells
5884 if ( !IsPositiveSpell(m_spellInfo->Id))
5885 m_caster->Attack(unitTarget,true);
5888 void Spell::EffectSummonCritter(uint32 i)
5890 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5891 return;
5892 Player* player = (Player*)m_caster;
5894 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5895 if(!pet_entry)
5896 return;
5898 Pet* old_critter = player->GetMiniPet();
5900 // for same pet just despawn
5901 if(old_critter && old_critter->GetEntry() == pet_entry)
5903 player->RemoveMiniPet();
5904 return;
5907 // despawn old pet before summon new
5908 if(old_critter)
5909 player->RemoveMiniPet();
5911 // summon new pet
5912 Pet* critter = new Pet(MINI_PET);
5914 Map *map = m_caster->GetMap();
5915 uint32 pet_number = objmgr.GeneratePetNumber();
5916 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5917 pet_entry, pet_number))
5919 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5920 delete critter;
5921 return;
5924 float x,y,z;
5925 // If dest location if present
5926 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5928 x = m_targets.m_destX;
5929 y = m_targets.m_destY;
5930 z = m_targets.m_destZ;
5932 // Summon if dest location not present near caster
5933 else
5934 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5936 critter->Relocate(x,y,z,m_caster->GetOrientation());
5938 if(!critter->IsPositionValid())
5940 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5941 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5942 delete critter;
5943 return;
5946 critter->SetOwnerGUID(m_caster->GetGUID());
5947 critter->SetCreatorGUID(m_caster->GetGUID());
5948 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5949 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5951 critter->AIM_Initialize();
5952 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5953 critter->SetMaxHealth(1);
5954 critter->SetHealth(1);
5955 critter->SetLevel(1);
5957 // set timer for unsummon
5958 int32 duration = GetSpellDuration(m_spellInfo);
5959 if(duration > 0)
5960 critter->SetDuration(duration);
5962 std::string name = player->GetName();
5963 name.append(petTypeSuffix[critter->getPetType()]);
5964 critter->SetName( name );
5965 player->SetMiniPet(critter);
5967 map->Add((Creature*)critter);
5970 void Spell::EffectKnockBack(uint32 i)
5972 if(!unitTarget || !m_caster)
5973 return;
5975 // Effect only works on players
5976 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5977 return;
5979 float vsin = sin(m_caster->GetAngle(unitTarget));
5980 float vcos = cos(m_caster->GetAngle(unitTarget));
5982 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5983 data.append(unitTarget->GetPackGUID());
5984 data << uint32(0); // Sequence
5985 data << float(vcos); // x direction
5986 data << float(vsin); // y direction
5987 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5988 data << float(damage/-10); // Z Movement speed (vertical)
5990 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5993 void Spell::EffectSendTaxi(uint32 i)
5995 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5996 return;
5998 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5999 if(!entry)
6000 return;
6002 std::vector<uint32> nodes;
6004 nodes.resize(2);
6005 nodes[0] = entry->from;
6006 nodes[1] = entry->to;
6008 uint32 mountid = 0;
6009 switch(m_spellInfo->Id)
6011 case 31606: //Stormcrow Amulet
6012 mountid = 17447;
6013 break;
6014 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
6015 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
6016 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
6017 mountid = 22840;
6018 break;
6019 case 34905: //Stealth Flight
6020 mountid = 6851;
6021 break;
6022 case 45883: //Amber Ledge to Beryl Point
6023 mountid = 23524;
6024 break;
6025 case 46064: //Amber Ledge to Coldarra
6026 mountid = 6371;
6027 break;
6028 case 53335: //Stormwind Harbor Flight - Peaceful
6029 mountid = 6852;
6030 break;
6033 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
6037 void Spell::EffectPlayerPull(uint32 i)
6039 if(!unitTarget || !m_caster)
6040 return;
6042 // Effect only works on players
6043 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6044 return;
6046 float vsin = sin(unitTarget->GetAngle(m_caster));
6047 float vcos = cos(unitTarget->GetAngle(m_caster));
6049 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
6050 data.append(unitTarget->GetPackGUID());
6051 data << uint32(0); // Sequence
6052 data << float(vcos); // x direction
6053 data << float(vsin); // y direction
6054 // Horizontal speed
6055 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6056 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6058 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6061 void Spell::EffectDispelMechanic(uint32 i)
6063 if(!unitTarget)
6064 return;
6066 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6068 Unit::AuraMap& Auras = unitTarget->GetAuras();
6069 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6071 next = iter;
6072 ++next;
6073 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6074 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6076 unitTarget->RemoveAurasDueToSpell(spell->Id);
6077 if(Auras.empty())
6078 break;
6079 else
6080 next = Auras.begin();
6083 return;
6086 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6088 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6089 return;
6090 Player *_player = (Player*)m_caster;
6091 Pet *pet = _player->GetPet();
6092 if(!pet)
6093 return;
6094 if(pet->isAlive())
6095 return;
6096 if(damage < 0)
6097 return;
6098 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6099 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6100 pet->setDeathState( ALIVE );
6101 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6102 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6104 pet->AIM_Initialize();
6106 _player->PetSpellInitialize();
6107 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6110 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6112 float mana = 0;
6113 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6115 if(!m_caster->m_TotemSlot[slot])
6116 continue;
6118 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
6119 if(totem && totem->isTotem())
6121 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6122 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6123 if(spellInfo)
6124 mana += spellInfo->manaCost * damage / 100;
6125 ((Totem*)totem)->UnSummon();
6129 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6130 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6133 void Spell::EffectDurabilityDamage(uint32 i)
6135 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6136 return;
6138 int32 slot = m_spellInfo->EffectMiscValue[i];
6140 // FIXME: some spells effects have value -1/-2
6141 // Possibly its mean -1 all player equipped items and -2 all items
6142 if(slot < 0)
6144 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6145 return;
6148 // invalid slot value
6149 if(slot >= INVENTORY_SLOT_BAG_END)
6150 return;
6152 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6153 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6156 void Spell::EffectDurabilityDamagePCT(uint32 i)
6158 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6159 return;
6161 int32 slot = m_spellInfo->EffectMiscValue[i];
6163 // FIXME: some spells effects have value -1/-2
6164 // Possibly its mean -1 all player equipped items and -2 all items
6165 if(slot < 0)
6167 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6168 return;
6171 // invalid slot value
6172 if(slot >= INVENTORY_SLOT_BAG_END)
6173 return;
6175 if(damage <= 0)
6176 return;
6178 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6179 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6182 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6184 if(!unitTarget)
6185 return;
6187 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6190 void Spell::EffectTransmitted(uint32 effIndex)
6192 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6194 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6196 if (!goinfo)
6198 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6199 return;
6202 float fx,fy,fz;
6204 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6206 fx = m_targets.m_destX;
6207 fy = m_targets.m_destY;
6208 fz = m_targets.m_destZ;
6210 //FIXME: this can be better check for most objects but still hack
6211 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6213 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6214 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6216 else
6218 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6219 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6220 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6222 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6225 Map *cMap = m_caster->GetMap();
6227 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6229 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6230 { // but this is not proper, we really need to ignore not materialized objects
6231 SendCastResult(SPELL_FAILED_NOT_HERE);
6232 SendChannelUpdate(0);
6233 return;
6236 // replace by water level in this case
6237 fz = cMap->GetWaterLevel(fx,fy);
6239 // if gameobject is summoning object, it should be spawned right on caster's position
6240 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6242 m_caster->GetPosition(fx,fy,fz);
6245 GameObject* pGameObj = new GameObject;
6247 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6248 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6250 delete pGameObj;
6251 return;
6254 int32 duration = GetSpellDuration(m_spellInfo);
6256 switch(goinfo->type)
6258 case GAMEOBJECT_TYPE_FISHINGNODE:
6260 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6261 // Orientation3
6262 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
6263 // Orientation4
6264 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
6265 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6267 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6268 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6269 int32 lastSec;
6270 switch(urand(0, 3))
6272 case 0: lastSec = 3; break;
6273 case 1: lastSec = 7; break;
6274 case 2: lastSec = 13; break;
6275 case 3: lastSec = 17; break;
6278 duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6279 break;
6281 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6283 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6285 pGameObj->AddUniqueUse((Player*)m_caster);
6286 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6288 break;
6290 case GAMEOBJECT_TYPE_FISHINGHOLE:
6291 case GAMEOBJECT_TYPE_CHEST:
6292 default:
6294 break;
6298 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6300 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6302 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6303 pGameObj->SetSpellId(m_spellInfo->Id);
6305 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6306 //m_caster->AddGameObject(pGameObj);
6307 //m_ObjToDel.push_back(pGameObj);
6309 cMap->Add(pGameObj);
6311 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6312 data << uint64(pGameObj->GetGUID());
6313 m_caster->SendMessageToSet(&data,true);
6315 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6317 GameObject* linkedGO = new GameObject;
6318 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6319 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6321 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6322 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6323 linkedGO->SetSpellId(m_spellInfo->Id);
6324 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6326 linkedGO->GetMap()->Add(linkedGO);
6328 else
6330 delete linkedGO;
6331 linkedGO = NULL;
6332 return;
6337 void Spell::EffectProspecting(uint32 /*i*/)
6339 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6340 return;
6342 Player* p_caster = (Player*)m_caster;
6343 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6344 return;
6346 if(itemTarget->GetCount() < 5)
6347 return;
6349 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6351 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6352 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6353 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6356 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6359 void Spell::EffectMilling(uint32 /*i*/)
6361 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6362 return;
6364 Player* p_caster = (Player*)m_caster;
6365 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6366 return;
6368 if(itemTarget->GetCount() < 5)
6369 return;
6371 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6373 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6374 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6375 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6378 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6381 void Spell::EffectSkill(uint32 /*i*/)
6383 sLog.outDebug("WORLD: SkillEFFECT");
6386 void Spell::EffectSummonDemon(uint32 i)
6388 float px = m_targets.m_destX;
6389 float py = m_targets.m_destY;
6390 float pz = m_targets.m_destZ;
6392 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6393 if (!Charmed)
6394 return;
6396 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6397 Charmed->SetLevel(m_caster->getLevel());
6399 // TODO: Add damage/mana/hp according to level
6401 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6403 // Enslave demon effect, without mana cost and cooldown
6404 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6406 // Inferno effect
6407 Charmed->CastSpell(Charmed, 22703, true, 0);
6411 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6412 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6413 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6414 This is why we use a half sec delay between the visual effect and the resurrection itself */
6415 void Spell::EffectSpiritHeal(uint32 /*i*/)
6418 if(!unitTarget || unitTarget->isAlive())
6419 return;
6420 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6421 return;
6422 if(!unitTarget->IsInWorld())
6423 return;
6425 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6426 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6427 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6428 ((Player*)unitTarget)->SpawnCorpseBones();
6432 // remove insignia spell effect
6433 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6435 sLog.outDebug("Effect: SkinPlayerCorpse");
6436 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6437 return;
6439 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6442 void Spell::EffectStealBeneficialBuff(uint32 i)
6444 sLog.outDebug("Effect: StealBeneficialBuff");
6446 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6447 return;
6449 std::vector <Aura *> steal_list;
6450 // Create dispel mask by dispel type
6451 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6452 Unit::AuraMap const& auras = unitTarget->GetAuras();
6453 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6455 Aura *aur = (*itr).second;
6456 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6458 // Need check for passive? this
6459 if (aur->IsPositive() && !aur->IsPassive())
6460 steal_list.push_back(aur);
6463 // Ok if exist some buffs for dispel try dispel it
6464 if (!steal_list.empty())
6466 std::list < std::pair<uint32,uint64> > success_list;
6467 int32 list_size = steal_list.size();
6468 // Dispell N = damage buffs (or while exist buffs for dispel)
6469 for (int32 count=0; count < damage && list_size > 0; ++count)
6471 // Random select buff for dispel
6472 Aura *aur = steal_list[urand(0, list_size-1)];
6473 // Not use chance for steal
6474 // TODO possible need do it
6475 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6477 // Remove buff from list for prevent doubles
6478 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6480 Aura *stealed = *j;
6481 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6483 j = steal_list.erase(j);
6484 --list_size;
6486 else
6487 ++j;
6490 // Really try steal and send log
6491 if (!success_list.empty())
6493 int32 count = success_list.size();
6494 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6495 data.append(unitTarget->GetPackGUID()); // Victim GUID
6496 data.append(m_caster->GetPackGUID()); // Caster GUID
6497 data << uint32(m_spellInfo->Id); // Dispell spell id
6498 data << uint8(0); // not used
6499 data << uint32(count); // count
6500 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6502 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6503 data << uint32(spellInfo->Id); // Spell Id
6504 data << uint8(0); // 0 - steals !=0 transfers
6505 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6507 m_caster->SendMessageToSet(&data, true);
6512 void Spell::EffectKillCredit(uint32 i)
6514 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6515 return;
6517 ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6520 void Spell::EffectQuestFail(uint32 i)
6522 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6523 return;
6525 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6528 void Spell::EffectActivateRune(uint32 eff_idx)
6530 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6531 return;
6533 Player *plr = (Player*)m_caster;
6535 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6536 return;
6538 for(uint32 j = 0; j < MAX_RUNES; ++j)
6540 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6542 plr->SetRuneCooldown(j, 0);
6547 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6549 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6550 ((Player*)unitTarget)->SetCanTitanGrip(true);
6553 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6555 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6556 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6557 return;
6559 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);