[7591] Implement 52375 and ranks.
[AHbot.git] / src / game / SpellEffects.cpp
blobd83af85b82ef5daf233e8d6ccbd048f1d0602e17
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32 /*i*/)
224 sLog.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32 /*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i)
234 if(!unitTarget || unitTarget->isAlive())
235 return;
237 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
238 return;
240 if(!unitTarget->IsInWorld())
241 return;
243 Player* pTarget = ((Player*)unitTarget);
245 if(pTarget->isRessurectRequested()) // already have one active request
246 return;
248 uint32 health = damage;
249 uint32 mana = m_spellInfo->EffectMiscValue[i];
250 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
251 SendResurrectRequest(pTarget);
254 void Spell::EffectInstaKill(uint32 /*i*/)
256 if( !unitTarget || !unitTarget->isAlive() )
257 return;
259 // Demonic Sacrifice
260 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
262 uint32 entry = unitTarget->GetEntry();
263 uint32 spellID;
264 switch(entry)
266 case 416: spellID=18789; break; //imp
267 case 417: spellID=18792; break; //fellhunter
268 case 1860: spellID=18790; break; //void
269 case 1863: spellID=18791; break; //succubus
270 case 17252: spellID=35701; break; //fellguard
271 default:
272 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
273 return;
276 m_caster->CastSpell(m_caster,spellID,true);
279 if(m_caster==unitTarget) // prevent interrupt message
280 finish();
282 uint32 health = unitTarget->GetHealth();
283 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i)
288 uint32 absorb = 0;
289 uint32 resist = 0;
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage = m_spellInfo->CalculateSimpleValue(i);
296 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
298 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
299 if(m_caster->GetTypeId() == TYPEID_PLAYER)
300 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE,damage);
303 void Spell::EffectSchoolDMG(uint32 effect_idx)
305 if( unitTarget && unitTarget->isAlive())
307 switch(m_spellInfo->SpellFamilyName)
309 case SPELLFAMILY_GENERIC:
311 //Gore
312 if(m_spellInfo->SpellIconID == 2269 )
314 damage+= rand()%2 ? damage : 0;
317 switch(m_spellInfo->Id) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
345 // Intercept (warrior spell trigger)
346 case 20253:
347 case 61491:
349 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
350 break;
353 break;
356 case SPELLFAMILY_MAGE:
358 // Arcane Blast
359 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
361 m_caster->CastSpell(m_caster,36032,true);
363 break;
365 case SPELLFAMILY_WARRIOR:
367 // Bloodthirst
368 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
370 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
372 // Shield Slam
373 else if(m_spellInfo->SpellFamilyFlags & 0x0000020000000000LL)
374 damage += int32(m_caster->GetShieldBlockValue());
375 // Victory Rush
376 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
378 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
379 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
383 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
386 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
390 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
391 if (pct > 0)
392 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
393 break;
395 break;
397 case SPELLFAMILY_WARLOCK:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
404 damage += int32(damage*0.25f);
406 break;
408 case SPELLFAMILY_PRIEST:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
412 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
413 break;
415 case SPELLFAMILY_DRUID:
417 // Ferocious Bite
418 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
422 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
423 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
424 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
425 m_caster->SetPower(POWER_ENERGY,0);
427 // Rake
428 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
430 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
432 // Swipe
433 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
435 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
439 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
441 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
442 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
443 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
445 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
446 break;
449 break;
451 case SPELLFAMILY_ROGUE:
453 // Envenom
454 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
459 Aura *poison = 0;
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
462 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
463 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
464 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
465 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
467 poison = *itr;
468 break;
470 // count consumed deadly poison doses at target
471 if (poison)
473 uint32 spellId = poison->GetId();
474 uint32 doses = poison->GetStackAmount();
475 if (doses > combo)
476 doses = combo;
477 for (int i=0; i< doses; i++)
478 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
479 damage *= doses;
480 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster->GetDummyAura(37169))
484 damage += ((Player*)m_caster)->GetComboPoints()*40;
487 // Eviscerate
488 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
490 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
493 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster->GetDummyAura(37169))
497 damage += combo*40;
500 // Gouge
501 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
503 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
505 // Instant Poison
506 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
508 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
510 // Wound Poison
511 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
513 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
515 break;
517 case SPELLFAMILY_HUNTER:
519 // Mongoose Bite
520 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
522 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
524 // Counterattack
525 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
527 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
529 // Arcane Shot
530 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
532 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
534 // Steady Shot
535 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
537 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
538 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
540 // Explosive Trap Effect
541 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
543 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
545 break;
547 case SPELLFAMILY_PALADIN:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
552 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
553 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
554 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
555 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
557 uint32 stacks = 0;
558 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
559 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
560 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
562 stacks = (*itr)->GetStackAmount();
563 break;
565 // + 10% for each application of Holy Vengeance on the target
566 if(stacks)
567 damage += damage * stacks * 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
572 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
573 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
574 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
575 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
580 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
581 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
582 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
583 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL)
588 // Add main hand dps * effect[2] amount
589 float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
590 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
591 damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
593 // Shield of Righteousness
594 else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL)
596 damage+=int32(m_caster->GetShieldBlockValue());
598 break;
602 if(damage >= 0)
603 m_damage+= damage;
607 void Spell::EffectDummy(uint32 i)
609 if(!unitTarget && !gameObjTarget && !itemTarget)
610 return;
612 // selection by spell family
613 switch(m_spellInfo->SpellFamilyName)
615 case SPELLFAMILY_GENERIC:
617 switch(m_spellInfo->Id )
619 case 8063: // Deviate Fish
621 if(m_caster->GetTypeId() != TYPEID_PLAYER)
622 return;
624 uint32 spell_id = 0;
625 switch(urand(1,5))
627 case 1: spell_id = 8064; break; // Sleepy
628 case 2: spell_id = 8065; break; // Invigorate
629 case 3: spell_id = 8066; break; // Shrink
630 case 4: spell_id = 8067; break; // Party Time!
631 case 5: spell_id = 8068; break; // Healthy Spirit
633 m_caster->CastSpell(m_caster,spell_id,true,NULL);
634 return;
636 case 8213: // Savory Deviate Delight
638 if(m_caster->GetTypeId() != TYPEID_PLAYER)
639 return;
641 uint32 spell_id = 0;
642 switch(urand(1,2))
644 // Flip Out - ninja
645 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
646 // Yaaarrrr - pirate
647 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
649 m_caster->CastSpell(m_caster,spell_id,true,NULL);
650 return;
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
656 return;
657 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
658 return;
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
662 case 12868:
664 if(!unitTarget)
665 return;
667 float damage;
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
671 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
672 else
673 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
675 switch (m_spellInfo->Id)
677 case 12850: damage *= 0.2f; break;
678 case 12162: damage *= 0.4f; break;
679 case 12868: damage *= 0.6f; break;
680 default:
681 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
682 return;
685 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
686 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
687 return;
689 case 13120: // net-o-matic
691 if(!unitTarget)
692 return;
694 uint32 spell_id = 0;
696 uint32 roll = urand(0, 99);
698 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
699 spell_id = 16566;
700 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
701 spell_id = 13119;
702 else // normal root
703 spell_id = 13099;
705 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
706 return;
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell || !unitTarget)
712 return;
714 switch(m_triggeredByAuraSpell->Id)
716 case 26467: // Persistent Shield
717 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
718 break;
719 default:
720 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
721 break;
723 return;
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
729 return;
731 Creature* creatureTarget = (Creature*)unitTarget;
732 creatureTarget->setDeathState(JUST_DIED);
733 creatureTarget->RemoveCorpse();
734 creatureTarget->SetHealth(0); // just for nice GM-mode view
735 return;
737 case 16589: // Noggenfogger Elixir
739 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
740 return;
742 uint32 spell_id = 0;
743 switch(urand(1,3))
745 case 1: spell_id = 16595; break;
746 case 2: spell_id = 16593; break;
747 default:spell_id = 16591; break;
750 m_caster->CastSpell(m_caster,spell_id,true,NULL);
751 return;
753 case 17251: // Spirit Healer Res
755 if(!unitTarget || !m_originalCaster)
756 return;
758 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
760 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
761 data << unitTarget->GetGUID();
762 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
764 return;
766 case 17271: // Test Fetid Skull
768 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
769 return;
771 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
773 m_caster->CastSpell(m_caster,spell_id,true,NULL);
774 return;
776 case 20577: // Cannibalize
777 if (unitTarget)
778 m_caster->CastSpell(m_caster,20578,false,NULL);
779 return;
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
783 return;
785 Creature* creatureTarget = (Creature*)unitTarget;
786 if(creatureTarget->isPet())
787 return;
789 GameObject* pGameObj = new GameObject;
791 Map *map = creatureTarget->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
795 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
796 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1) )
798 delete pGameObj;
799 return;
802 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
803 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
804 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
805 pGameObj->SetSpellId(m_spellInfo->Id);
807 creatureTarget->setDeathState(JUST_DIED);
808 creatureTarget->RemoveCorpse();
809 creatureTarget->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
812 map->Add(pGameObj);
814 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
815 data << uint64(pGameObj->GetGUID());
816 m_caster->SendMessageToSet(&data,true);
818 return;
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem) return;
822 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
823 return;
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem) return;
826 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
827 return;
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem) return;
830 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
831 return;
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem) return;
834 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
835 return;
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r = irand(0, 119);
839 if ( r < 20 ) // 1/6 polymorph
840 m_caster->CastSpell(m_caster,23444,true);
841 else if ( r < 100 ) // 4/6 evil twin
842 m_caster->CastSpell(m_caster,23445,true);
843 else // 1/6 miss the target
844 m_caster->CastSpell(m_caster,36902,true);
845 return;
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster->CastSpell(m_caster,23441,true);
850 else // failure
851 m_caster->CastSpell(m_caster,23446,true);
852 return;
853 case 23645: // Hourglass Sand
854 m_caster->RemoveAurasDueToSpell(23170);
855 return;
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster->CastSpell(m_caster,23782,true);
858 m_caster->CastSpell(m_caster,23783,true);
859 return;
860 case 25860: // Reindeer Transformation
862 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
863 return;
865 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
866 float speed = m_caster->GetSpeedRate(MOVE_RUN);
868 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed >= 4.1f)
872 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
873 else if (flyspeed >= 3.8f)
874 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
875 else if (flyspeed >= 1.6f)
876 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
877 else if (speed >= 2.0f)
878 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
879 else
880 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
882 return;
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
889 m_caster->CastSpell(unitTarget,29294,true);
890 return;
892 case 28730: // Arcane Torrent (Mana)
894 Aura * dummy = m_caster->GetDummyAura(28734);
895 if (dummy)
897 int32 bp = damage * dummy->GetStackAmount();
898 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
899 m_caster->RemoveAurasDueToSpell(28734);
901 return;
903 case 29200: // Purify Helboar Meat
905 if( m_caster->GetTypeId() != TYPEID_PLAYER )
906 return;
908 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
910 m_caster->CastSpell(m_caster,spell_id,true,NULL);
911 return;
913 case 29858: // Soulshatter
914 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
915 m_caster->CastSpell(unitTarget,32835,true);
916 return;
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem) return;
919 if(roll_chance_i(86)) // success
920 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
921 else // backfire in 14% casts
922 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
923 return;
924 case 30507: // Poultryizer
925 if (!m_CastItem) return;
926 if(roll_chance_i(80)) // success
927 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
928 else // backfire 20%
929 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
930 return;
931 case 33060: // Make a Wish
933 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
934 return;
936 uint32 spell_id = 0;
938 switch(urand(1,5))
940 case 1: spell_id = 33053; break;
941 case 2: spell_id = 33057; break;
942 case 3: spell_id = 33059; break;
943 case 4: spell_id = 33062; break;
944 case 5: spell_id = 33064; break;
947 m_caster->CastSpell(m_caster,spell_id,true,NULL);
948 return;
950 case 35745:
952 uint32 spell_id;
953 switch(m_caster->GetAreaId())
955 case 3900: spell_id = 35743; break;
956 case 3742: spell_id = 35744; break;
957 default: return;
960 m_caster->CastSpell(m_caster,spell_id,true);
961 return;
963 case 37674: // Chaos Blast
965 if(!unitTarget)
966 return;
968 int32 basepoints0 = 100;
969 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
970 return;
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
975 uint32 newitemid;
976 switch(urand(1,20))
978 case 1: newitemid = 32688; break;
979 case 2: newitemid = 32689; break;
980 case 3: newitemid = 32690; break;
981 case 4: newitemid = 32691; break;
982 case 5: newitemid = 32692; break;
983 case 6: newitemid = 32693; break;
984 case 7: newitemid = 32700; break;
985 case 8: newitemid = 32701; break;
986 case 9: newitemid = 32702; break;
987 case 10: newitemid = 32703; break;
988 case 11: newitemid = 32704; break;
989 case 12: newitemid = 32705; break;
990 case 13: newitemid = 32706; break;
991 case 14: newitemid = 32707; break;
992 case 15: newitemid = 32708; break;
993 case 16: newitemid = 32709; break;
994 case 17: newitemid = 32710; break;
995 case 18: newitemid = 32711; break;
996 case 19: newitemid = 32712; break;
997 case 20: newitemid = 32713; break;
998 default:
999 return;
1002 DoCreateItem(i,newitemid);
1003 return;
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1007 case 43723:
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1010 return;
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1013 return;
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1019 return;
1021 Creature* creatureTarget = (Creature*)unitTarget;
1023 creatureTarget->setDeathState(JUST_DIED);
1024 creatureTarget->RemoveCorpse();
1025 creatureTarget->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster->CastSpell(m_caster,42337,true,NULL);
1029 return;
1031 case 34665: //Administer Antidote
1033 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1034 return;
1036 if(!unitTarget)
1037 return;
1039 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1040 if(!tempSummon)
1041 return;
1043 uint32 health = tempSummon->GetHealth();
1045 float x = tempSummon->GetPositionX();
1046 float y = tempSummon->GetPositionY();
1047 float z = tempSummon->GetPositionZ();
1048 float o = tempSummon->GetOrientation();
1049 tempSummon->UnSummon();
1051 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1052 if (!pCreature)
1053 return;
1055 pCreature->SetHealth(health);
1056 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992,pCreature);
1058 if (pCreature->AI())
1059 pCreature->AI()->AttackStart(m_caster);
1061 return;
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster->CastSpell(m_caster, 45009, true);
1067 return;
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster->CastSpell(m_caster, 45088, true);
1073 return;
1075 case 50243: // Teach Language
1077 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1078 return;
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1082 return;
1083 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1085 // 1000001 - gnomish binary
1086 m_caster->CastSpell(m_caster, 50242, true);
1088 else
1090 // 01001000 - goblin binary
1091 m_caster->CastSpell(m_caster, 50246, true);
1094 return;
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1099 return;
1101 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1102 bg->EventPlayerDroppedFlag((Player*)m_caster);
1104 m_caster->CastSpell(m_caster, 30452, true, NULL);
1105 return;
1107 case 52308:
1109 switch(i)
1111 case 0:
1113 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1114 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1116 if (m_caster->HasAura(reqAuraID,0))
1117 m_caster->CastSpell(m_caster,spellID,true,NULL);
1118 return;
1120 case 1:
1121 return; // additional data for dummy[0]
1123 return;
1125 case 53341:
1126 case 53343:
1128 m_caster->CastSpell(m_caster,54586,true);
1129 return;
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo->SpellIconID)
1139 // Berserking (troll racial traits)
1140 case 1661:
1142 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1143 int32 melee_mod = 10;
1144 if (healthPerc <= 40)
1145 melee_mod = 30;
1146 if (healthPerc < 100 && healthPerc > 40)
1147 melee_mod = 10+(100-healthPerc)/3;
1149 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1 = (5-melee_mod);
1151 int32 hasteModBasePoints2 = 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1155 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1156 return;
1159 break;
1161 case SPELLFAMILY_MAGE:
1162 switch(m_spellInfo->Id )
1164 case 11958: // Cold Snap
1166 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1167 return;
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1173 if (itr->second->state == PLAYERSPELL_REMOVED)
1174 continue;
1176 uint32 classspell = itr->first;
1177 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1179 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1180 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1181 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1183 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1185 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1186 data << uint32(classspell);
1187 data << uint64(m_caster->GetGUID());
1188 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1191 return;
1193 case 32826:
1195 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1201 return;
1204 break;
1205 case SPELLFAMILY_WARRIOR:
1206 // Charge
1207 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1209 int32 chargeBasePoints0 = damage;
1210 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1211 return;
1213 // Execute
1214 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1216 if(!unitTarget)
1217 return;
1219 uint32 rage = m_caster->GetPower(POWER_RAGE);
1220 // Glyph of Execution bonus
1221 if (Aura *aura = m_caster->GetDummyAura(58367))
1222 rage+=aura->GetModifier()->m_amount;
1224 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1225 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1226 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1227 m_caster->SetPower(POWER_RAGE,0);
1228 return;
1230 // Slam
1231 if(m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL)
1233 if(!unitTarget)
1234 return;
1235 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1236 m_damage+=damage;
1237 return;
1239 switch(m_spellInfo->Id)
1241 // Warrior's Wrath
1242 case 21977:
1244 if(!unitTarget)
1245 return;
1246 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1247 return;
1249 // Last Stand
1250 case 12975:
1252 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1253 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1254 return;
1256 // Bloodthirst
1257 case 23881:
1259 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1260 return;
1263 break;
1264 case SPELLFAMILY_WARLOCK:
1265 // Life Tap
1266 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1268 // In 303 exist spirit depend
1269 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1270 switch (m_spellInfo->Id)
1272 case 1454: damage+=spirit; break;
1273 case 1455: damage+=spirit*15/10; break;
1274 case 1456: damage+=spirit*2; break;
1275 case 11687: damage+=spirit*25/10; break;
1276 case 11688:
1277 case 11689:
1278 case 27222:
1279 case 57946: damage+=spirit*3; break;
1280 default:
1281 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1282 return;
1284 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1285 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1286 if(int32(unitTarget->GetHealth()) > damage)
1288 // Shouldn't Appear in Combat Log
1289 unitTarget->ModifyHealth(-damage);
1291 int32 mana = damage;
1292 // Improved Life Tap mod
1293 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1294 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1296 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1297 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1299 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1301 // Mana Feed
1302 int32 manaFeedVal = 0;
1303 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1304 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1306 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1307 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1309 if(manaFeedVal > 0)
1311 manaFeedVal = manaFeedVal * mana / 100;
1312 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1315 else
1316 SendCastResult(SPELL_FAILED_FIZZLE);
1317 return;
1319 break;
1320 case SPELLFAMILY_PRIEST:
1321 // Penance
1322 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1324 if (!unitTarget)
1325 return;
1327 int hurt = 0;
1328 int heal = 0;
1329 switch(m_spellInfo->Id)
1331 case 47540: hurt = 47758; heal = 47757; break;
1332 case 53005: hurt = 53001; heal = 52986; break;
1333 case 53006: hurt = 53002; heal = 52987; break;
1334 case 53007: hurt = 53003; heal = 52988; break;
1335 default:
1336 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1337 return;
1339 if (m_caster->IsFriendlyTo(unitTarget))
1340 m_caster->CastSpell(unitTarget, heal, true, 0);
1341 else
1342 m_caster->CastSpell(unitTarget, hurt, true, 0);
1343 return;
1345 break;
1346 case SPELLFAMILY_DRUID:
1347 // Starfall
1348 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100LL)
1350 //Shapeshifting into an animal form or mounting cancels the effect.
1351 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1353 if(m_triggeredByAuraSpell)
1354 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1355 return;
1358 //Any effect which causes you to lose control of your character will supress the starfall effect.
1359 if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1360 return;
1362 switch(m_spellInfo->Id)
1364 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1365 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1366 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1367 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1368 default:
1369 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1370 return;
1373 break;
1374 case SPELLFAMILY_ROGUE:
1375 switch(m_spellInfo->Id )
1377 case 5938: // Shiv
1379 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1380 return;
1382 Player *pCaster = ((Player*)m_caster);
1384 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1385 if(!item)
1386 return;
1388 // all poison enchantments is temporary
1389 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1390 if(!enchant_id)
1391 return;
1393 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1394 if(!pEnchant)
1395 return;
1397 for (int s=0;s<3;s++)
1399 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1400 continue;
1402 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1403 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1404 continue;
1406 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1409 m_caster->CastSpell(unitTarget, 5940, true);
1410 return;
1412 case 14185: // Preparation Rogue
1414 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1415 return;
1417 //immediately finishes the cooldown on certain Rogue abilities
1418 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1419 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1421 uint32 classspell = itr->first;
1422 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1424 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1426 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1428 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1429 data << uint32(classspell);
1430 data << uint64(m_caster->GetGUID());
1431 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1434 return;
1436 case 31231: // Cheat Death
1438 m_caster->CastSpell(m_caster,45182,true);
1439 return;
1442 break;
1443 case SPELLFAMILY_HUNTER:
1444 // Steady Shot
1445 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1447 if( !unitTarget || !unitTarget->isAlive())
1448 return;
1450 bool found = false;
1452 // check dazed affect
1453 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1454 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1456 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1458 found = true;
1459 break;
1463 if(found)
1464 m_damage+= damage;
1465 return;
1468 switch(m_spellInfo->Id)
1470 case 23989: //Readiness talent
1472 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1473 return;
1475 //immediately finishes the cooldown for hunter abilities
1476 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1477 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1479 uint32 classspell = itr->first;
1480 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1482 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1484 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1486 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1487 data << uint32(classspell);
1488 data << uint64(m_caster->GetGUID());
1489 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1492 return;
1494 case 37506: // Scatter Shot
1496 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1497 return;
1499 // break Auto Shot and autohit
1500 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1501 m_caster->AttackStop();
1502 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1503 return;
1506 break;
1507 case SPELLFAMILY_PALADIN:
1508 switch(m_spellInfo->SpellIconID)
1510 case 156: // Holy Shock
1512 if(!unitTarget)
1513 return;
1515 int hurt = 0;
1516 int heal = 0;
1518 switch(m_spellInfo->Id)
1520 case 20473: hurt = 25912; heal = 25914; break;
1521 case 20929: hurt = 25911; heal = 25913; break;
1522 case 20930: hurt = 25902; heal = 25903; break;
1523 case 27174: hurt = 27176; heal = 27175; break;
1524 case 33072: hurt = 33073; heal = 33074; break;
1525 case 48824: hurt = 48822; heal = 48820; break;
1526 case 48825: hurt = 48823; heal = 48821; break;
1527 default:
1528 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1529 return;
1532 if(m_caster->IsFriendlyTo(unitTarget))
1533 m_caster->CastSpell(unitTarget, heal, true, 0);
1534 else
1535 m_caster->CastSpell(unitTarget, hurt, true, 0);
1537 return;
1539 case 561: // Judgement of command
1541 if(!unitTarget)
1542 return;
1544 uint32 spell_id = m_currentBasePoints[i]+1;
1545 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1546 if(!spell_proto)
1547 return;
1549 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1551 // decreased damage (/2) for non-stunned target.
1552 SpellModifier *mod = new SpellModifier;
1553 mod->op = SPELLMOD_DAMAGE;
1554 mod->value = -50;
1555 mod->type = SPELLMOD_PCT;
1556 mod->spellId = m_spellInfo->Id;
1557 mod->mask = 0x0000020000000000LL;
1558 mod->mask2= 0LL;
1560 ((Player*)m_caster)->AddSpellMod(mod, true);
1561 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1562 // mod deleted
1563 ((Player*)m_caster)->AddSpellMod(mod, false);
1565 else
1566 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1568 return;
1572 switch(m_spellInfo->Id)
1574 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1575 case 20187:
1577 if (!unitTarget)
1578 return;
1579 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1580 return;
1582 case 31789: // Righteous Defense (step 1)
1584 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1586 // non-standard cast requirement check
1587 if (!unitTarget || unitTarget->getAttackers().empty())
1589 // clear cooldown at fail
1590 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1592 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1594 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1595 data << uint32(m_spellInfo->Id);
1596 data << uint64(m_caster->GetGUID());
1597 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1600 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1601 return;
1604 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1605 // Clear targets for eff 1
1606 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1607 ihit->effectMask &= ~(1<<1);
1609 // not empty (checked)
1610 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1612 // chance to be selected from list
1613 float chance = 100.0f/attackers.size();
1614 uint32 count=0;
1615 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1617 if(!roll_chance_f(chance))
1618 continue;
1619 ++count;
1620 AddUnitTarget((*aItr), 1);
1623 // now let next effect cast spell at each target.
1624 return;
1626 case 37877: // Blessing of Faith
1628 if(!unitTarget)
1629 return;
1631 uint32 spell_id = 0;
1632 switch(unitTarget->getClass())
1634 case CLASS_DRUID: spell_id = 37878; break;
1635 case CLASS_PALADIN: spell_id = 37879; break;
1636 case CLASS_PRIEST: spell_id = 37880; break;
1637 case CLASS_SHAMAN: spell_id = 37881; break;
1638 default: return; // ignore for not healing classes
1641 m_caster->CastSpell(m_caster,spell_id,true);
1642 return;
1645 break;
1646 case SPELLFAMILY_SHAMAN:
1647 //Shaman Rockbiter Weapon
1648 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1650 // TODO: use expect spell for enchant (if exist talent)
1651 // In 3.0.3 no mods present for rockbiter
1652 uint32 spell_id = 0;
1653 switch(m_spellInfo->Id)
1655 case 8017: spell_id = 36494; break; // Rank 1
1656 case 8018: spell_id = 36750; break; // Rank 2
1657 case 8019: spell_id = 36755; break; // Rank 3
1658 case 10399: spell_id = 36759; break; // Rank 4
1659 default:
1660 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1661 return;
1664 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1666 if(!spellInfo)
1668 sLog.outError("WORLD: unknown spell id %i", spell_id);
1669 return;
1672 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1673 return;
1675 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1677 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1679 if(item->IsFitToSpellRequirements(m_spellInfo))
1681 Spell *spell = new Spell(m_caster, spellInfo, true);
1683 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1684 // at calculation applied affect from Elemental Weapons talent
1685 // real enchantment damage-1
1686 spell->m_currentBasePoints[1] = damage-1;
1688 SpellCastTargets targets;
1689 targets.setItemTarget( item );
1690 spell->prepare(&targets);
1694 return;
1696 // Healing Stream Totem
1697 if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
1699 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1700 return;
1702 // Mana Spring Totem
1703 if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
1705 if(unitTarget->getPowerType()!=POWER_MANA)
1706 return;
1707 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1708 return;
1710 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1712 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1713 return;
1714 // Glyph of Mana Tide
1715 Unit *owner = m_caster->GetOwner();
1716 if (owner)
1717 if (Aura *dummy = owner->GetDummyAura(55441))
1718 damage+=dummy->GetModifier()->m_amount;
1719 // Regenerate 6% of Total Mana Every 3 secs
1720 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1721 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1722 return;
1724 // Lava Lash
1725 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1727 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1728 return;
1729 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1730 if (item)
1732 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1733 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1734 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1736 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1737 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1738 (*itr)->GetCastItemGUID() == item->GetGUID())
1740 m_damage += m_damage * damage / 100;
1741 return;
1745 return;
1747 break;
1748 case SPELLFAMILY_DEATHKNIGHT:
1749 // Death Coil
1750 if(m_spellInfo->SpellFamilyFlags & 0x002000LL)
1752 if(m_caster->IsFriendlyTo(unitTarget))
1754 if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1755 return;
1757 // first rank have special multiplier
1758 int32 bp = damage * 1.5f;
1759 m_caster->CastCustomSpell(unitTarget,47633,&bp,NULL,NULL,true);
1761 else
1763 // first rank have special multiplier
1764 int32 bp = damage;
1765 m_caster->CastCustomSpell(unitTarget,47632,&bp,NULL,NULL,true);
1767 return;
1769 break;
1772 // pet auras
1773 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1775 m_caster->AddPetAura(petSpell);
1776 return;
1779 // Script based implementation. Must be used only for not good for implementation in core spell effects
1780 // So called only for not proccessed cases
1781 if(gameObjTarget)
1782 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
1783 else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
1784 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
1785 else if(itemTarget)
1786 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
1789 void Spell::EffectTriggerSpellWithValue(uint32 i)
1791 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1793 // normal case
1794 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1796 if(!spellInfo)
1798 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1799 return;
1802 int32 bp = damage;
1803 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1806 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1808 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1809 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1811 if(!spellInfo)
1813 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1814 return;
1817 finish();
1818 Spell *spell = new Spell(m_caster, spellInfo, true);
1820 SpellCastTargets targets;
1821 targets.setUnitTarget( unitTarget);
1822 spell->prepare(&targets);
1824 m_caster->SetCurrentCastedSpell(spell);
1825 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1829 void Spell::EffectForceCast(uint32 i)
1831 if( !unitTarget )
1832 return;
1834 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1836 // normal case
1837 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1839 if(!spellInfo)
1841 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1842 return;
1845 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1848 void Spell::EffectTriggerSpell(uint32 i)
1850 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1852 // special cases
1853 switch(triggered_spell_id)
1855 // Vanish
1856 case 18461:
1858 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1859 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1860 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1862 // if this spell is given to NPC it must handle rest by it's own AI
1863 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1864 return;
1866 // get highest rank of the Stealth spell
1867 uint32 spellId = 0;
1868 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1869 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1871 // only highest rank is shown in spell book, so simply check if shown in spell book
1872 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1873 continue;
1875 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1876 if (!spellInfo)
1877 continue;
1879 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1881 spellId = spellInfo->Id;
1882 break;
1886 // no Stealth spell found
1887 if (!spellId)
1888 return;
1890 // reset cooldown on it if needed
1891 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1892 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1894 m_caster->CastSpell(m_caster, spellId, true);
1895 return;
1897 // just skip
1898 case 23770: // Sayge's Dark Fortune of *
1899 // not exist, common cooldown can be implemented in scripts if need.
1900 return;
1901 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1902 case 29284:
1904 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1905 if (!spell)
1906 return;
1908 for (int i=0; i < spell->StackAmount; ++i)
1909 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1910 return;
1912 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1913 case 29286:
1915 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1916 if (!spell)
1917 return;
1919 for (int i=0; i < spell->StackAmount; ++i)
1920 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1921 return;
1923 // Righteous Defense
1924 case 31980:
1926 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1927 return;
1929 // Cloak of Shadows
1930 case 35729 :
1932 Unit::AuraMap& Auras = m_caster->GetAuras();
1933 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1935 // remove all harmful spells on you...
1936 if( // ignore positive and passive auras
1937 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1938 // ignore physical auras
1939 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1941 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1942 iter = Auras.begin();
1945 return;
1947 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1948 case 41967:
1950 if (Unit *pet = m_caster->GetPet())
1951 pet->CastSpell(pet, 28305, true);
1952 return;
1956 // normal case
1957 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1959 if(!spellInfo)
1961 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1962 return;
1965 // some triggered spells require specific equipment
1966 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1968 // main hand weapon required
1969 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1971 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1973 // skip spell if no weapon in slot or broken
1974 if(!item || item->IsBroken() )
1975 return;
1977 // skip spell if weapon not fit to triggered spell
1978 if(!item->IsFitToSpellRequirements(spellInfo))
1979 return;
1982 // offhand hand weapon required
1983 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1985 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1987 // skip spell if no weapon in slot or broken
1988 if(!item || item->IsBroken() )
1989 return;
1991 // skip spell if weapon not fit to triggered spell
1992 if(!item->IsFitToSpellRequirements(spellInfo))
1993 return;
1997 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1998 bool instant = false;
1999 for(uint32 j = i+1; j < 3; ++j)
2001 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
2003 instant = true;
2004 break;
2008 if(instant)
2010 if (unitTarget)
2011 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
2013 else
2014 m_TriggerSpells.push_back(spellInfo);
2017 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2019 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2021 // normal case
2022 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2024 if(!spellInfo)
2026 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2027 m_spellInfo->Id,effect_idx,triggered_spell_id);
2028 return;
2031 if (m_CastItem)
2032 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2034 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2037 void Spell::EffectJump(uint32 i)
2039 if(m_caster->isInFlight())
2040 return;
2042 // Init dest coordinates
2043 float x,y,z,o;
2044 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2046 x = m_targets.m_destX;
2047 y = m_targets.m_destY;
2048 z = m_targets.m_destZ;
2050 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2052 // explicit cast data from client or server-side cast
2053 // some spell at client send caster
2054 Unit* pTarget = NULL;
2055 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2056 pTarget = m_targets.getUnitTarget();
2057 else if(unitTarget->getVictim())
2058 pTarget = m_caster->getVictim();
2059 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2060 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2062 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2064 else
2065 o = m_caster->GetOrientation();
2067 else if(unitTarget)
2069 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2070 o = m_caster->GetOrientation();
2072 else if(gameObjTarget)
2074 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2075 o = m_caster->GetOrientation();
2077 else
2079 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2080 return;
2083 m_caster->NearTeleportTo(x,y,z,o,true);
2086 void Spell::EffectTeleportUnits(uint32 i)
2088 if(!unitTarget || unitTarget->isInFlight())
2089 return;
2091 switch (m_spellInfo->EffectImplicitTargetB[i])
2093 case TARGET_INNKEEPER_COORDINATES:
2095 // Only players can teleport to innkeeper
2096 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2097 return;
2099 ((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);
2100 return;
2102 case TARGET_TABLE_X_Y_Z_COORDINATES:
2104 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2105 if(!st)
2107 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2108 return;
2111 if(st->target_mapId==unitTarget->GetMapId())
2112 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2113 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2114 ((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);
2115 break;
2117 case TARGET_BEHIND_VICTIM:
2119 Unit *pTarget = NULL;
2121 // explicit cast data from client or server-side cast
2122 // some spell at client send caster
2123 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2124 pTarget = m_targets.getUnitTarget();
2125 else if(unitTarget->getVictim())
2126 pTarget = unitTarget->getVictim();
2127 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2128 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2130 // Init dest coordinates
2131 float x = m_targets.m_destX;
2132 float y = m_targets.m_destY;
2133 float z = m_targets.m_destZ;
2134 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2135 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2136 return;
2138 default:
2140 // If not exist data for dest location - return
2141 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2143 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2144 return;
2146 // Init dest coordinates
2147 uint32 mapid = m_caster->GetMapId();
2148 float x = m_targets.m_destX;
2149 float y = m_targets.m_destY;
2150 float z = m_targets.m_destZ;
2151 float orientation = unitTarget->GetOrientation();
2152 // Teleport
2153 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2154 return;
2158 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2159 switch ( m_spellInfo->Id )
2161 // Dimensional Ripper - Everlook
2162 case 23442:
2164 int32 r = irand(0, 119);
2165 if ( r >= 70 ) // 7/12 success
2167 if ( r < 100 ) // 4/12 evil twin
2168 m_caster->CastSpell(m_caster,23445,true);
2169 else // 1/12 fire
2170 m_caster->CastSpell(m_caster,23449,true);
2172 return;
2174 // Ultrasafe Transporter: Toshley's Station
2175 case 36941:
2177 if ( roll_chance_i(50) ) // 50% success
2179 int32 rand_eff = urand(1,7);
2180 switch ( rand_eff )
2182 case 1:
2183 // soul split - evil
2184 m_caster->CastSpell(m_caster,36900,true);
2185 break;
2186 case 2:
2187 // soul split - good
2188 m_caster->CastSpell(m_caster,36901,true);
2189 break;
2190 case 3:
2191 // Increase the size
2192 m_caster->CastSpell(m_caster,36895,true);
2193 break;
2194 case 4:
2195 // Decrease the size
2196 m_caster->CastSpell(m_caster,36893,true);
2197 break;
2198 case 5:
2199 // Transform
2201 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2202 m_caster->CastSpell(m_caster,36897,true);
2203 else
2204 m_caster->CastSpell(m_caster,36899,true);
2205 break;
2207 case 6:
2208 // chicken
2209 m_caster->CastSpell(m_caster,36940,true);
2210 break;
2211 case 7:
2212 // evil twin
2213 m_caster->CastSpell(m_caster,23445,true);
2214 break;
2217 return;
2219 // Dimensional Ripper - Area 52
2220 case 36890:
2222 if ( roll_chance_i(50) ) // 50% success
2224 int32 rand_eff = urand(1,4);
2225 switch ( rand_eff )
2227 case 1:
2228 // soul split - evil
2229 m_caster->CastSpell(m_caster,36900,true);
2230 break;
2231 case 2:
2232 // soul split - good
2233 m_caster->CastSpell(m_caster,36901,true);
2234 break;
2235 case 3:
2236 // Increase the size
2237 m_caster->CastSpell(m_caster,36895,true);
2238 break;
2239 case 4:
2240 // Transform
2242 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2243 m_caster->CastSpell(m_caster,36897,true);
2244 else
2245 m_caster->CastSpell(m_caster,36899,true);
2246 break;
2250 return;
2255 void Spell::EffectApplyAura(uint32 i)
2257 if(!unitTarget)
2258 return;
2260 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2261 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2262 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2263 return;
2265 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2266 if(!caster)
2267 return;
2269 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2271 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2273 // Now Reduce spell duration using data received at spell hit
2274 int32 duration = Aur->GetAuraMaxDuration();
2275 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2276 Aur->setDiminishGroup(m_diminishGroup);
2278 // if Aura removed and deleted, do not continue.
2279 if(duration== 0 && !(Aur->IsPermanent()))
2281 delete Aur;
2282 return;
2285 if(duration != Aur->GetAuraMaxDuration())
2287 Aur->SetAuraMaxDuration(duration);
2288 Aur->SetAuraDuration(duration);
2291 bool added = unitTarget->AddAura(Aur);
2293 // Aura not added and deleted in AddAura call;
2294 if (!added)
2295 return;
2297 // found crash at character loading, broken pointer to Aur...
2298 // Aur was deleted in AddAura()...
2299 if(!Aur)
2300 return;
2302 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2303 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2304 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2307 void Spell::EffectUnlearnSpecialization( uint32 i )
2309 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2310 return;
2312 Player *_player = (Player*)unitTarget;
2313 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2315 _player->removeSpell(spellToUnlearn);
2317 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2320 void Spell::EffectPowerDrain(uint32 i)
2322 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2323 return;
2325 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2327 if(!unitTarget)
2328 return;
2329 if(!unitTarget->isAlive())
2330 return;
2331 if(unitTarget->getPowerType() != drain_power)
2332 return;
2333 if(damage < 0)
2334 return;
2336 uint32 curPower = unitTarget->GetPower(drain_power);
2338 //add spell damage bonus
2339 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2341 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2342 uint32 power = damage;
2343 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2344 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2346 int32 new_damage;
2347 if(curPower < power)
2348 new_damage = curPower;
2349 else
2350 new_damage = power;
2352 unitTarget->ModifyPower(drain_power,-new_damage);
2354 // Don`t restore from self drain
2355 if(drain_power == POWER_MANA && m_caster != unitTarget)
2357 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2358 if(manaMultiplier==0)
2359 manaMultiplier = 1;
2361 if(Player *modOwner = m_caster->GetSpellModOwner())
2362 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2364 int32 gain = int32(new_damage*manaMultiplier);
2366 m_caster->ModifyPower(POWER_MANA,gain);
2367 //send log
2368 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2372 void Spell::EffectSendEvent(uint32 EffectIndex)
2375 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2377 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2378 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2381 void Spell::EffectPowerBurn(uint32 i)
2383 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2384 return;
2386 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2388 if(!unitTarget)
2389 return;
2390 if(!unitTarget->isAlive())
2391 return;
2392 if(unitTarget->getPowerType()!=powertype)
2393 return;
2394 if(damage < 0)
2395 return;
2397 int32 curPower = int32(unitTarget->GetPower(powertype));
2399 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2400 uint32 power = damage;
2401 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2402 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2404 int32 new_damage = (curPower < power) ? curPower : power;
2406 unitTarget->ModifyPower(powertype,-new_damage);
2407 float multiplier = m_spellInfo->EffectMultipleValue[i];
2409 if(Player *modOwner = m_caster->GetSpellModOwner())
2410 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2412 new_damage = int32(new_damage*multiplier);
2413 m_damage+=new_damage;
2416 void Spell::EffectHeal( uint32 /*i*/ )
2418 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2420 // Try to get original caster
2421 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2423 // Skip if m_originalCaster not available
2424 if (!caster)
2425 return;
2427 int32 addhealth = damage;
2429 // Vessel of the Naaru (Vial of the Sunwell trinket)
2430 if (m_spellInfo->Id == 45064)
2432 // Amount of heal - depends from stacked Holy Energy
2433 int damageAmount = 0;
2434 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2435 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2436 if((*i)->GetId() == 45062)
2437 damageAmount+=(*i)->GetModifier()->m_amount;
2438 if (damageAmount)
2439 m_caster->RemoveAurasDueToSpell(45062);
2441 addhealth += damageAmount;
2443 // Swiftmend - consumes Regrowth or Rejuvenation
2444 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2446 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2447 // find most short by duration
2448 Aura *targetAura = NULL;
2449 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2451 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2452 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2454 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2455 targetAura = *i;
2459 if(!targetAura)
2461 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2462 return;
2464 int idx = 0;
2465 while(idx < 3)
2467 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2468 break;
2469 idx++;
2472 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2473 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2474 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2476 addhealth += tickheal * tickcount;
2478 else
2479 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2481 m_healing+=addhealth;
2485 void Spell::EffectHealPct( uint32 /*i*/ )
2487 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2489 // Try to get original caster
2490 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2492 // Skip if m_originalCaster not available
2493 if (!caster)
2494 return;
2496 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2497 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2499 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2500 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2502 if(caster->GetTypeId()==TYPEID_PLAYER)
2503 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2504 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2508 void Spell::EffectHealMechanical( uint32 /*i*/ )
2510 // Mechanic creature type should be correctly checked by targetCreatureType field
2511 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2513 // Try to get original caster
2514 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2516 // Skip if m_originalCaster not available
2517 if (!caster)
2518 return;
2520 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2521 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2522 unitTarget->ModifyHealth( int32(damage) );
2526 void Spell::EffectHealthLeech(uint32 i)
2528 if(!unitTarget)
2529 return;
2530 if(!unitTarget->isAlive())
2531 return;
2533 if(damage < 0)
2534 return;
2536 sLog.outDebug("HealthLeech :%i", damage);
2538 float multiplier = m_spellInfo->EffectMultipleValue[i];
2540 if(Player *modOwner = m_caster->GetSpellModOwner())
2541 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2543 int32 new_damage = int32(damage*multiplier);
2544 uint32 curHealth = unitTarget->GetHealth();
2545 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2546 if(curHealth < new_damage)
2547 new_damage = curHealth;
2549 if(m_caster->isAlive())
2551 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2553 m_caster->ModifyHealth(new_damage);
2555 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2556 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2558 // m_healthLeech+=tmpvalue;
2559 // m_damage+=new_damage;
2562 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2564 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2565 return;
2567 Player* player = (Player*)unitTarget;
2569 uint32 newitemid = itemtype;
2570 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2571 if(!pProto)
2573 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2574 return;
2577 uint32 num_to_add;
2579 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2580 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2582 int32 basePoints = m_currentBasePoints[i];
2583 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2584 if (randomPoints)
2585 num_to_add = basePoints + irand(1, randomPoints);
2586 else
2587 num_to_add = basePoints + 1;
2589 else if (pProto->MaxCount == 1)
2590 num_to_add = 1;
2591 else if(player->getLevel() >= m_spellInfo->spellLevel)
2593 int32 basePoints = m_currentBasePoints[i];
2594 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2595 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2597 else
2598 num_to_add = 2;
2600 if (num_to_add < 1)
2601 num_to_add = 1;
2602 if (num_to_add > pProto->GetMaxStackSize())
2603 num_to_add = pProto->GetMaxStackSize();
2605 // init items_count to 1, since 1 item will be created regardless of specialization
2606 int items_count=1;
2607 // the chance to create additional items
2608 float additionalCreateChance=0.0f;
2609 // the maximum number of created additional items
2610 uint8 additionalMaxNum=0;
2611 // get the chance and maximum number for creating extra items
2612 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2614 // roll with this chance till we roll not to create or we create the max num
2615 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2616 ++items_count;
2619 // really will be created more items
2620 num_to_add *= items_count;
2622 // can the player store the new item?
2623 ItemPosCountVec dest;
2624 uint32 no_space = 0;
2625 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2626 if( msg != EQUIP_ERR_OK )
2628 // convert to possible store amount
2629 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2630 num_to_add -= no_space;
2631 else
2633 // if not created by another reason from full inventory or unique items amount limitation
2634 player->SendEquipError( msg, NULL, NULL );
2635 return;
2639 if(num_to_add)
2641 // create the new item and store it
2642 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2644 // was it successful? return error if not
2645 if(!pItem)
2647 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2648 return;
2651 // set the "Crafted by ..." property of the item
2652 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2653 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2655 // send info to the client
2656 if(pItem)
2657 player->SendNewItem(pItem, num_to_add, true, true);
2659 // we succeeded in creating at least one item, so a levelup is possible
2660 player->UpdateCraftSkill(m_spellInfo->Id);
2663 // for battleground marks send by mail if not add all expected
2664 if(no_space > 0 )
2666 BattleGroundTypeId bgType;
2667 switch(m_spellInfo->Id)
2669 case SPELL_AV_MARK_WINNER:
2670 case SPELL_AV_MARK_LOSER:
2671 bgType = BATTLEGROUND_AV;
2672 break;
2673 case SPELL_WS_MARK_WINNER:
2674 case SPELL_WS_MARK_LOSER:
2675 bgType = BATTLEGROUND_WS;
2676 break;
2677 case SPELL_AB_MARK_WINNER:
2678 case SPELL_AB_MARK_LOSER:
2679 bgType = BATTLEGROUND_AB;
2680 break;
2681 default:
2682 return;
2685 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2686 bg->SendRewardMarkByMail(player,newitemid,no_space);
2690 void Spell::EffectCreateItem(uint32 i)
2692 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2695 void Spell::EffectCreateItem2(uint32 i)
2697 // special case: generate using spell_loot_template
2698 if(!m_spellInfo->EffectItemType[i])
2700 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2701 return;
2703 // create some random items
2704 ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
2705 return;
2707 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2710 void Spell::EffectPersistentAA(uint32 i)
2712 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2714 if(Player* modOwner = m_caster->GetSpellModOwner())
2715 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2717 int32 duration = GetSpellDuration(m_spellInfo);
2718 DynamicObject* dynObj = new DynamicObject;
2719 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))
2721 delete dynObj;
2722 return;
2724 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2725 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2726 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2727 m_caster->AddDynObject(dynObj);
2728 dynObj->GetMap()->Add(dynObj);
2731 void Spell::EffectEnergize(uint32 i)
2733 if(!unitTarget)
2734 return;
2735 if(!unitTarget->isAlive())
2736 return;
2738 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2739 return;
2741 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2743 // Some level depends spells
2744 int multiplier = 0;
2745 int level_diff = 0;
2746 switch (m_spellInfo->Id)
2748 // Restore Energy
2749 case 9512:
2750 level_diff = m_caster->getLevel() - 40;
2751 multiplier = 2;
2752 break;
2753 // Blood Fury
2754 case 24571:
2755 level_diff = m_caster->getLevel() - 60;
2756 multiplier = 10;
2757 break;
2758 // Burst of Energy
2759 case 24532:
2760 level_diff = m_caster->getLevel() - 60;
2761 multiplier = 4;
2762 break;
2763 default:
2764 break;
2767 if (level_diff > 0)
2768 damage -= multiplier * level_diff;
2770 if(damage < 0)
2771 return;
2773 if(unitTarget->GetMaxPower(power) == 0)
2774 return;
2776 unitTarget->ModifyPower(power,damage);
2777 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2779 // Mad Alchemist's Potion
2780 if (m_spellInfo->Id == 45051)
2782 // find elixirs on target
2783 uint32 elixir_mask = 0;
2784 Unit::AuraMap& Auras = unitTarget->GetAuras();
2785 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2787 uint32 spell_id = itr->second->GetId();
2788 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2789 elixir_mask |= mask;
2792 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2793 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2795 // get all available elixirs by mask and spell level
2796 std::vector<uint32> elixirs;
2797 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2798 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2800 if (itr->second & elixir_mask)
2802 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2803 continue;
2805 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2806 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2807 continue;
2809 elixirs.push_back(itr->first);
2813 if (!elixirs.empty())
2815 // cast random elixir on target
2816 uint32 rand_spell = urand(0,elixirs.size()-1);
2817 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2822 void Spell::EffectEnergisePct(uint32 i)
2824 if(!unitTarget)
2825 return;
2826 if(!unitTarget->isAlive())
2827 return;
2829 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2830 return;
2832 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2834 uint32 maxPower = unitTarget->GetMaxPower(power);
2835 if(maxPower == 0)
2836 return;
2838 uint32 gain = damage * maxPower / 100;
2839 unitTarget->ModifyPower(power, gain);
2840 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2843 void Spell::SendLoot(uint64 guid, LootType loottype)
2845 Player* player = (Player*)m_caster;
2846 if (!player)
2847 return;
2849 if (gameObjTarget)
2851 if (Script->GOHello(player, gameObjTarget))
2852 return;
2854 switch (gameObjTarget->GetGoType())
2856 case GAMEOBJECT_TYPE_DOOR:
2857 case GAMEOBJECT_TYPE_BUTTON:
2858 gameObjTarget->UseDoorOrButton();
2859 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2860 return;
2862 case GAMEOBJECT_TYPE_QUESTGIVER:
2863 // start or end quest
2864 player->PrepareQuestMenu(guid);
2865 player->SendPreparedQuest(guid);
2866 return;
2868 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2869 // triggering linked GO
2870 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2871 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2872 return;
2874 case GAMEOBJECT_TYPE_GOOBER:
2875 // goober_scripts can be triggered if the player don't have the quest
2876 if (gameObjTarget->GetGOInfo()->goober.eventId)
2878 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2879 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2882 // cast goober spell
2883 if (gameObjTarget->GetGOInfo()->goober.questId)
2884 ///Quest require to be active for GO using
2885 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2886 return;
2888 gameObjTarget->AddUniqueUse(player);
2889 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2891 //TODO? Objective counting called without spell check but with quest objective check
2892 // if send spell id then this line will duplicate to spell casting call (double counting)
2893 // So we or have this line and not required in quest_template have reqSpellIdN
2894 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2895 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2897 // triggering linked GO
2898 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2899 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2901 return;
2903 case GAMEOBJECT_TYPE_CHEST:
2904 // TODO: possible must be moved to loot release (in different from linked triggering)
2905 if (gameObjTarget->GetGOInfo()->chest.eventId)
2907 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2908 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2911 // triggering linked GO
2912 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2913 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2915 // Don't return, let loots been taken
2919 // Send loot
2920 player->SendLoot(guid, loottype);
2923 void Spell::EffectOpenLock(uint32 effIndex)
2925 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2927 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2928 return;
2931 Player* player = (Player*)m_caster;
2933 uint32 lockId = 0;
2934 uint64 guid = 0;
2936 // Get lockId
2937 if(gameObjTarget)
2939 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2940 // Arathi Basin banner opening !
2941 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2942 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2944 //CanUseBattleGroundObject() already called in CheckCast()
2945 // in battleground check
2946 if(BattleGround *bg = player->GetBattleGround())
2948 // check if it's correct bg
2949 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2950 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2951 return;
2954 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2956 //CanUseBattleGroundObject() already called in CheckCast()
2957 // in battleground check
2958 if(BattleGround *bg = player->GetBattleGround())
2960 if(bg->GetTypeID() == BATTLEGROUND_EY)
2961 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2962 return;
2965 lockId = gameObjTarget->GetLockId();
2966 guid = gameObjTarget->GetGUID();
2968 else if(itemTarget)
2970 lockId = itemTarget->GetProto()->LockID;
2971 guid = itemTarget->GetGUID();
2973 else
2975 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2976 return;
2979 SkillType skillId = SKILL_NONE;
2980 int32 reqSkillValue = 0;
2981 int32 skillValue;
2983 SpellCastResult res = CanOpenLock(effIndex,lockId,skillId,reqSkillValue,skillValue);
2984 if(res != SPELL_CAST_OK)
2986 SendCastResult(res);
2987 return;
2990 SendLoot(guid, LOOT_SKINNING);
2992 // not allow use skill grow at item base open
2993 if(!m_CastItem && skillId != SKILL_NONE)
2995 // update skill if really known
2996 if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
2998 if(gameObjTarget)
3000 // Allow one skill-up until respawned
3001 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3002 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
3003 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3005 else if(itemTarget)
3007 // Do one skill-up
3008 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3014 void Spell::EffectSummonChangeItem(uint32 i)
3016 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3017 return;
3019 Player *player = (Player*)m_caster;
3021 // applied only to using item
3022 if(!m_CastItem)
3023 return;
3025 // ... only to item in own inventory/bank/equip_slot
3026 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3027 return;
3029 uint32 newitemid = m_spellInfo->EffectItemType[i];
3030 if(!newitemid)
3031 return;
3033 uint16 pos = m_CastItem->GetPos();
3035 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3036 if( !pNewItem )
3037 return;
3039 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3041 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3042 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3045 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3047 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3048 player->DurabilityLoss(pNewItem, loosePercent);
3051 if( player->IsInventoryPos( pos ) )
3053 ItemPosCountVec dest;
3054 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3055 if( msg == EQUIP_ERR_OK )
3057 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3059 // prevent crash at access and unexpected charges counting with item update queue corrupt
3060 if(m_CastItem==m_targets.getItemTarget())
3061 m_targets.setItemTarget(NULL);
3063 m_CastItem = NULL;
3065 player->StoreItem( dest, pNewItem, true);
3066 return;
3069 else if( player->IsBankPos ( pos ) )
3071 ItemPosCountVec dest;
3072 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3073 if( msg == EQUIP_ERR_OK )
3075 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3077 // prevent crash at access and unexpected charges counting with item update queue corrupt
3078 if(m_CastItem==m_targets.getItemTarget())
3079 m_targets.setItemTarget(NULL);
3081 m_CastItem = NULL;
3083 player->BankItem( dest, pNewItem, true);
3084 return;
3087 else if( player->IsEquipmentPos ( pos ) )
3089 uint16 dest;
3090 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3091 if( msg == EQUIP_ERR_OK )
3093 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3095 // prevent crash at access and unexpected charges counting with item update queue corrupt
3096 if(m_CastItem==m_targets.getItemTarget())
3097 m_targets.setItemTarget(NULL);
3099 m_CastItem = NULL;
3101 player->EquipItem( dest, pNewItem, true);
3102 player->AutoUnequipOffhandIfNeed();
3103 return;
3107 // fail
3108 delete pNewItem;
3111 void Spell::EffectOpenSecretSafe(uint32 i)
3113 EffectOpenLock(i); //no difference for now
3116 void Spell::EffectProficiency(uint32 /*i*/)
3118 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3119 return;
3120 Player *p_target = (Player*)unitTarget;
3122 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3123 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3125 p_target->AddWeaponProficiency(subClassMask);
3126 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3128 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3130 p_target->AddArmorProficiency(subClassMask);
3131 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3135 void Spell::EffectApplyAreaAura(uint32 i)
3137 if(!unitTarget)
3138 return;
3139 if(!unitTarget->isAlive())
3140 return;
3142 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3143 unitTarget->AddAura(Aur);
3146 void Spell::EffectSummonType(uint32 i)
3148 switch(m_spellInfo->EffectMiscValueB[i])
3150 case SUMMON_TYPE_GUARDIAN:
3151 case SUMMON_TYPE_POSESSED:
3152 case SUMMON_TYPE_POSESSED2:
3153 case SUMMON_TYPE_FORCE_OF_NATURE:
3154 case SUMMON_TYPE_GUARDIAN2:
3155 EffectSummonGuardian(i);
3156 break;
3157 case SUMMON_TYPE_WILD:
3158 EffectSummonWild(i);
3159 break;
3160 case SUMMON_TYPE_DEMON:
3161 EffectSummonDemon(i);
3162 break;
3163 case SUMMON_TYPE_SUMMON:
3164 EffectSummon(i);
3165 break;
3166 case SUMMON_TYPE_CRITTER:
3167 case SUMMON_TYPE_CRITTER2:
3168 case SUMMON_TYPE_CRITTER3:
3169 EffectSummonCritter(i);
3170 break;
3171 case SUMMON_TYPE_TOTEM_SLOT1:
3172 case SUMMON_TYPE_TOTEM_SLOT2:
3173 case SUMMON_TYPE_TOTEM_SLOT3:
3174 case SUMMON_TYPE_TOTEM_SLOT4:
3175 case SUMMON_TYPE_TOTEM:
3176 EffectSummonTotem(i);
3177 break;
3178 case SUMMON_TYPE_UNKNOWN1:
3179 case SUMMON_TYPE_UNKNOWN2:
3180 case SUMMON_TYPE_UNKNOWN3:
3181 case SUMMON_TYPE_UNKNOWN4:
3182 case SUMMON_TYPE_UNKNOWN5:
3183 break;
3184 default:
3185 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3186 break;
3190 void Spell::EffectSummon(uint32 i)
3192 if(m_caster->GetPetGUID())
3193 return;
3195 if(!unitTarget)
3196 return;
3197 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3198 if(!pet_entry)
3199 return;
3200 uint32 level = m_caster->getLevel();
3201 Pet* spawnCreature = new Pet(SUMMON_PET);
3203 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3205 // set timer for unsummon
3206 int32 duration = GetSpellDuration(m_spellInfo);
3207 if(duration > 0)
3208 spawnCreature->SetDuration(duration);
3210 return;
3213 Map *map = m_caster->GetMap();
3214 uint32 pet_number = objmgr.GeneratePetNumber();
3215 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
3216 m_spellInfo->EffectMiscValue[i], pet_number))
3218 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3219 delete spawnCreature;
3220 return;
3223 // Summon in dest location
3224 float x,y,z;
3225 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3227 x = m_targets.m_destX;
3228 y = m_targets.m_destY;
3229 z = m_targets.m_destZ;
3231 else
3232 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3234 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3236 if(!spawnCreature->IsPositionValid())
3238 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3239 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3240 delete spawnCreature;
3241 return;
3244 // set timer for unsummon
3245 int32 duration = GetSpellDuration(m_spellInfo);
3246 if(duration > 0)
3247 spawnCreature->SetDuration(duration);
3249 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3250 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3251 spawnCreature->setPowerType(POWER_MANA);
3252 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3253 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3254 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3255 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3256 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3257 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3258 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3259 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3260 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3262 spawnCreature->InitStatsForLevel(level);
3264 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3266 spawnCreature->AIM_Initialize();
3267 spawnCreature->InitPetCreateSpells();
3268 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3269 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3271 std::string name = m_caster->GetName();
3272 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3273 spawnCreature->SetName( name );
3275 map->Add((Creature*)spawnCreature);
3277 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3279 m_caster->SetPet(spawnCreature);
3280 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3281 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3282 ((Player*)m_caster)->PetSpellInitialize();
3286 void Spell::EffectLearnSpell(uint32 i)
3288 if(!unitTarget)
3289 return;
3291 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3293 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3294 EffectLearnPetSpell(i);
3296 return;
3299 Player *player = (Player*)unitTarget;
3301 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3302 player->learnSpell(spellToLearn,false);
3304 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3307 void Spell::EffectDispel(uint32 i)
3309 if(!unitTarget)
3310 return;
3312 // Fill possible dispell list
3313 std::vector <Aura *> dispel_list;
3315 // Create dispel mask by dispel type
3316 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3317 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3318 Unit::AuraMap const& auras = unitTarget->GetAuras();
3319 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3321 Aura *aur = (*itr).second;
3322 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3324 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3326 bool positive = true;
3327 if (!aur->IsPositive())
3328 positive = false;
3329 else
3330 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3332 // do not remove positive auras if friendly target
3333 // negative auras if non-friendly target
3334 if(positive == unitTarget->IsFriendlyTo(m_caster))
3335 continue;
3337 // Add aura to dispel list
3338 dispel_list.push_back(aur);
3341 // Ok if exist some buffs for dispel try dispel it
3342 if (!dispel_list.empty())
3344 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3345 std::list < uint32 > fail_list; // spell_id
3346 int32 list_size = dispel_list.size();
3347 // Dispell N = damage buffs (or while exist buffs for dispel)
3348 for (int32 count=0; count < damage && list_size > 0; ++count)
3350 // Random select buff for dispel
3351 Aura *aur = dispel_list[urand(0, list_size-1)];
3353 SpellEntry const* spellInfo = aur->GetSpellProto();
3354 // Base dispel chance
3355 // TODO: possible chance depend from spell level??
3356 int32 miss_chance = 0;
3357 // Apply dispel mod from aura caster
3358 if (Unit *caster = aur->GetCaster())
3360 if ( Player* modOwner = caster->GetSpellModOwner() )
3361 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3363 // Try dispel
3364 if (roll_chance_i(miss_chance))
3365 fail_list.push_back(aur->GetId());
3366 else
3367 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3368 // Remove buff from list for prevent doubles
3369 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3371 Aura *dispeled = *j;
3372 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3374 j = dispel_list.erase(j);
3375 --list_size;
3377 else
3378 ++j;
3381 // Send success log and really remove auras
3382 if (!success_list.empty())
3384 int32 count = success_list.size();
3385 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3386 data.append(unitTarget->GetPackGUID()); // Victim GUID
3387 data.append(m_caster->GetPackGUID()); // Caster GUID
3388 data << uint32(m_spellInfo->Id); // Dispell spell id
3389 data << uint8(0); // not used
3390 data << uint32(count); // count
3391 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3393 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3394 data << uint32(spellInfo->Id); // Spell Id
3395 data << uint8(0); // 0 - dispeled !=0 cleansed
3396 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3398 m_caster->SendMessageToSet(&data, true);
3400 // On succes dispel
3401 // Devour Magic
3402 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3404 uint32 heal_spell = 0;
3405 switch (m_spellInfo->Id)
3407 case 19505: heal_spell = 19658; break;
3408 case 19731: heal_spell = 19732; break;
3409 case 19734: heal_spell = 19733; break;
3410 case 19736: heal_spell = 19735; break;
3411 case 27276: heal_spell = 27278; break;
3412 case 27277: heal_spell = 27279; break;
3413 default:
3414 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3415 break;
3417 if (heal_spell)
3418 m_caster->CastSpell(m_caster, heal_spell, true);
3421 // Send fail log to client
3422 if (!fail_list.empty())
3424 // Failed to dispell
3425 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3426 data << uint64(m_caster->GetGUID()); // Caster GUID
3427 data << uint64(unitTarget->GetGUID()); // Victim GUID
3428 data << uint32(m_spellInfo->Id); // Dispell spell id
3429 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3430 data << uint32(*j); // Spell Id
3431 m_caster->SendMessageToSet(&data, true);
3436 void Spell::EffectDualWield(uint32 /*i*/)
3438 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3439 ((Player*)unitTarget)->SetCanDualWield(true);
3442 void Spell::EffectPull(uint32 /*i*/)
3444 // TODO: create a proper pull towards distract spell center for distract
3445 sLog.outDebug("WORLD: Spell Effect DUMMY");
3448 void Spell::EffectDistract(uint32 /*i*/)
3450 // Check for possible target
3451 if (!unitTarget || unitTarget->isInCombat())
3452 return;
3454 // target must be OK to do this
3455 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3456 return;
3458 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3460 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3462 // For players just turn them
3463 WorldPacket data;
3464 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3465 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3466 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3468 else
3470 // Set creature Distracted, Stop it, And turn it
3471 unitTarget->SetOrientation(angle);
3472 unitTarget->StopMoving();
3473 unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS);
3477 void Spell::EffectPickPocket(uint32 /*i*/)
3479 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3480 return;
3482 // victim must be creature and attackable
3483 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3484 return;
3486 // victim have to be alive and humanoid or undead
3487 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3489 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3491 if (chance > irand(0, 19))
3493 // Stealing successful
3494 //sLog.outDebug("Sending loot from pickpocket");
3495 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3497 else
3499 // Reveal action + get attack
3500 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3501 if (((Creature*)unitTarget)->AI())
3502 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3507 void Spell::EffectAddFarsight(uint32 i)
3509 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3510 int32 duration = GetSpellDuration(m_spellInfo);
3511 DynamicObject* dynObj = new DynamicObject;
3512 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))
3514 delete dynObj;
3515 return;
3517 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3518 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3519 m_caster->AddDynObject(dynObj);
3520 dynObj->GetMap()->Add(dynObj);
3521 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3522 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3525 void Spell::EffectSummonWild(uint32 i)
3527 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3528 if(!creature_entry)
3529 return;
3531 uint32 level = m_caster->getLevel();
3533 // level of creature summoned using engineering item based at engineering skill level
3534 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3536 ItemPrototype const *proto = m_CastItem->GetProto();
3537 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3539 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3540 if(skill202)
3542 level = skill202/5;
3547 // select center of summon position
3548 float center_x = m_targets.m_destX;
3549 float center_y = m_targets.m_destY;
3550 float center_z = m_targets.m_destZ;
3552 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3554 int32 amount = damage > 0 ? damage : 1;
3556 for(int32 count = 0; count < amount; ++count)
3558 float px, py, pz;
3559 // If dest location if present
3560 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3562 // Summon 1 unit in dest location
3563 if (count == 0)
3565 px = m_targets.m_destX;
3566 py = m_targets.m_destY;
3567 pz = m_targets.m_destZ;
3569 // Summon in random point all other units if location present
3570 else
3571 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3573 // Summon if dest location not present near caster
3574 else
3575 m_caster->GetClosePoint(px,py,pz,3.0f);
3577 int32 duration = GetSpellDuration(m_spellInfo);
3579 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3581 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3585 void Spell::EffectSummonGuardian(uint32 i)
3587 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3588 if(!pet_entry)
3589 return;
3591 // Jewelery statue case (totem like)
3592 if(m_spellInfo->SpellIconID==2056)
3594 EffectSummonTotem(i);
3595 return;
3598 // set timer for unsummon
3599 int32 duration = GetSpellDuration(m_spellInfo);
3601 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3602 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3603 // so this code hack in fact
3604 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3605 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3606 return; // find old guardian, ignore summon
3608 // in another case summon new
3609 uint32 level = m_caster->getLevel();
3611 // level of pet summoned using engineering item based at engineering skill level
3612 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3614 ItemPrototype const *proto = m_CastItem->GetProto();
3615 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3617 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3618 if(skill202)
3620 level = skill202/5;
3625 // select center of summon position
3626 float center_x = m_targets.m_destX;
3627 float center_y = m_targets.m_destY;
3628 float center_z = m_targets.m_destZ;
3630 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3632 int32 amount = damage > 0 ? damage : 1;
3634 for(int32 count = 0; count < amount; ++count)
3636 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3638 Map *map = m_caster->GetMap();
3639 uint32 pet_number = objmgr.GeneratePetNumber();
3640 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3641 m_spellInfo->EffectMiscValue[i], pet_number))
3643 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3644 delete spawnCreature;
3645 return;
3648 float px, py, pz;
3649 // If dest location if present
3650 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3652 // Summon 1 unit in dest location
3653 if (count == 0)
3655 px = m_targets.m_destX;
3656 py = m_targets.m_destY;
3657 pz = m_targets.m_destZ;
3659 // Summon in random point all other units if location present
3660 else
3661 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3663 // Summon if dest location not present near caster
3664 else
3665 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3667 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3669 if(!spawnCreature->IsPositionValid())
3671 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3672 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3673 delete spawnCreature;
3674 return;
3677 if(duration > 0)
3678 spawnCreature->SetDuration(duration);
3680 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3681 spawnCreature->setPowerType(POWER_MANA);
3682 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3683 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3684 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3685 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3686 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3687 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3688 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3690 spawnCreature->InitStatsForLevel(level);
3691 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3693 spawnCreature->AIM_Initialize();
3695 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3696 ((Player*)m_caster)->AddGuardian(spawnCreature);
3698 map->Add((Creature*)spawnCreature);
3702 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3704 if(!unitTarget)
3705 return;
3707 if(unitTarget->isInFlight())
3708 return;
3710 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3712 float fx,fy,fz;
3713 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3715 unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster);
3718 void Spell::EffectLearnSkill(uint32 i)
3720 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3721 return;
3723 if(damage < 0)
3724 return;
3726 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3727 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3728 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3731 void Spell::EffectAddHonor(uint32 /*i*/)
3733 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3734 return;
3736 // not scale value for item based reward (/10 value expected)
3737 if(m_CastItem)
3739 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage/10);
3740 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
3741 return;
3744 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3745 if( damage <= 50)
3747 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
3748 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
3749 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
3751 else
3753 //maybe we have correct honor_gain in damage already
3754 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3755 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3759 void Spell::EffectTradeSkill(uint32 /*i*/)
3761 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3762 return;
3763 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3764 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3765 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3768 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3770 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3771 return;
3772 if (!itemTarget)
3773 return;
3775 Player* p_caster = (Player*)m_caster;
3777 // not grow at item use at item case
3778 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3780 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3781 if (!enchant_id)
3782 return;
3784 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3785 if(!pEnchant)
3786 return;
3788 // item can be in trade slot and have owner diff. from caster
3789 Player* item_owner = itemTarget->GetOwner();
3790 if(!item_owner)
3791 return;
3793 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3795 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3796 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3797 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3798 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3801 // remove old enchanting before applying new if equipped
3802 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3804 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3806 // add new enchanting if equipped
3807 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3810 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3812 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3813 return;
3814 if (!itemTarget)
3815 return;
3817 Player* p_caster = (Player*)m_caster;
3819 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3820 if (!enchant_id)
3821 return;
3823 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3824 if(!pEnchant)
3825 return;
3827 // support only enchantings with add socket in this slot
3829 bool add_socket = false;
3830 for(int i = 0; i < 3; ++i)
3832 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3834 add_socket = true;
3835 break;
3838 if(!add_socket)
3840 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.",
3841 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3842 return;
3846 // item can be in trade slot and have owner diff. from caster
3847 Player* item_owner = itemTarget->GetOwner();
3848 if(!item_owner)
3849 return;
3851 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3853 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3854 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3855 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3856 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3859 // remove old enchanting before applying new if equipped
3860 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3862 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3864 // add new enchanting if equipped
3865 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3868 void Spell::EffectEnchantItemTmp(uint32 i)
3870 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3871 return;
3873 Player* p_caster = (Player*)m_caster;
3875 if(!itemTarget)
3876 return;
3878 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3880 // Shaman Rockbiter Weapon
3881 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3883 int32 enchnting_damage = m_currentBasePoints[1]+1;
3885 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3886 // with already applied percent bonus from Elemental Weapons talent
3887 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3888 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3889 switch(enchnting_damage)
3891 // Rank 1
3892 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3893 // Rank 2
3894 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3895 case 5: enchant_id = 3025; break; // 20%
3896 // Rank 3
3897 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3898 case 7: enchant_id = 3027; break; // 20%
3899 // Rank 4
3900 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3901 case 10: enchant_id = 503; break; // 14%
3902 case 11: enchant_id = 3031; break; // 20%
3903 // Rank 5
3904 case 15: enchant_id = 3035; break; // 0%
3905 case 16: enchant_id = 1663; break; // 7%
3906 case 17: enchant_id = 3033; break; // 14%
3907 case 18: enchant_id = 3034; break; // 20%
3908 // Rank 6
3909 case 28: enchant_id = 3038; break; // 0%
3910 case 29: enchant_id = 683; break; // 7%
3911 case 31: enchant_id = 3036; break; // 14%
3912 case 33: enchant_id = 3037; break; // 20%
3913 // Rank 7
3914 case 40: enchant_id = 3041; break; // 0%
3915 case 42: enchant_id = 1664; break; // 7%
3916 case 45: enchant_id = 3039; break; // 14%
3917 case 48: enchant_id = 3040; break; // 20%
3918 // Rank 8
3919 case 49: enchant_id = 3044; break; // 0%
3920 case 52: enchant_id = 2632; break; // 7%
3921 case 55: enchant_id = 3042; break; // 14%
3922 case 58: enchant_id = 3043; break; // 20%
3923 // Rank 9
3924 case 62: enchant_id = 2633; break; // 0%
3925 case 66: enchant_id = 3018; break; // 7%
3926 case 70: enchant_id = 3019; break; // 14%
3927 case 74: enchant_id = 3020; break; // 20%
3928 default:
3929 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3930 return;
3934 if (!enchant_id)
3936 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3937 return;
3940 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3941 if(!pEnchant)
3943 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3944 return;
3947 // select enchantment duration
3948 uint32 duration;
3950 // rogue family enchantments exception by duration
3951 if(m_spellInfo->Id==38615)
3952 duration = 1800; // 30 mins
3953 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3954 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3955 duration = 3600; // 1 hour
3956 // shaman family enchantments
3957 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3958 duration = 1800; // 30 mins
3959 // other cases with this SpellVisual already selected
3960 else if(m_spellInfo->SpellVisual[0]==215)
3961 duration = 1800; // 30 mins
3962 // some fishing pole bonuses
3963 else if(m_spellInfo->SpellVisual[0]==563)
3964 duration = 600; // 10 mins
3965 // shaman rockbiter enchantments
3966 else if(m_spellInfo->SpellVisual[0]==0)
3967 duration = 1800; // 30 mins
3968 else if(m_spellInfo->Id==29702)
3969 duration = 300; // 5 mins
3970 else if(m_spellInfo->Id==37360)
3971 duration = 300; // 5 mins
3972 // default case
3973 else
3974 duration = 3600; // 1 hour
3976 // item can be in trade slot and have owner diff. from caster
3977 Player* item_owner = itemTarget->GetOwner();
3978 if(!item_owner)
3979 return;
3981 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3983 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3984 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3985 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3986 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3989 // remove old enchanting before applying new if equipped
3990 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3992 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3994 // add new enchanting if equipped
3995 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3998 void Spell::EffectTameCreature(uint32 /*i*/)
4000 if(m_caster->GetPetGUID())
4001 return;
4003 if(!unitTarget)
4004 return;
4006 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4007 return;
4009 Creature* creatureTarget = (Creature*)unitTarget;
4011 if(creatureTarget->isPet())
4012 return;
4014 if(m_caster->getClass() != CLASS_HUNTER)
4015 return;
4017 // cast finish successfully
4018 //SendChannelUpdate(0);
4019 finish();
4021 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4023 // kill original creature
4024 creatureTarget->setDeathState(JUST_DIED);
4025 creatureTarget->RemoveCorpse();
4026 creatureTarget->SetHealth(0); // just for nice GM-mode view
4028 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4030 // prepare visual effect for levelup
4031 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4033 // add to world
4034 pet->GetMap()->Add((Creature*)pet);
4036 // visual effect for levelup
4037 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4039 // caster have pet now
4040 m_caster->SetPet(pet);
4042 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4044 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4045 ((Player*)m_caster)->PetSpellInitialize();
4049 void Spell::EffectSummonPet(uint32 i)
4051 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4053 Pet *OldSummon = m_caster->GetPet();
4055 // if pet requested type already exist
4056 if( OldSummon )
4058 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4060 // pet in corpse state can't be summoned
4061 if( OldSummon->isDead() )
4062 return;
4064 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4065 OldSummon->SetMapId(m_caster->GetMapId());
4067 float px, py, pz;
4068 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4070 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4071 m_caster->GetMap()->Add((Creature*)OldSummon);
4073 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4075 ((Player*)m_caster)->PetSpellInitialize();
4077 return;
4080 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4081 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4082 else
4083 return;
4086 Pet* NewSummon = new Pet;
4088 // petentry==0 for hunter "call pet" (current pet summoned if any)
4089 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4091 if(NewSummon->getPetType()==SUMMON_PET)
4093 // Remove Demonic Sacrifice auras (known pet)
4094 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4095 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4097 if((*itr)->GetModifier()->m_miscvalue==2228)
4099 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4100 itr = auraClassScripts.begin();
4102 else
4103 ++itr;
4107 return;
4110 // not error in case fail hunter call pet
4111 if(!petentry)
4113 delete NewSummon;
4114 return;
4117 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4119 if(!cInfo)
4121 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4122 delete NewSummon;
4123 return;
4126 Map *map = m_caster->GetMap();
4127 uint32 pet_number = objmgr.GeneratePetNumber();
4128 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4129 petentry, pet_number))
4131 delete NewSummon;
4132 return;
4135 float px, py, pz;
4136 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4138 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4140 if(!NewSummon->IsPositionValid())
4142 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4143 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4144 delete NewSummon;
4145 return;
4148 uint32 petlevel = m_caster->getLevel();
4149 NewSummon->setPetType(SUMMON_PET);
4151 uint32 faction = m_caster->getFaction();
4152 if(m_caster->GetTypeId() == TYPEID_UNIT)
4154 if ( ((Creature*)m_caster)->isTotem() )
4155 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4156 else
4157 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4160 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4161 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4162 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4163 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4164 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4165 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4166 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4167 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4168 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4169 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4171 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4172 // this enables pet details window (Shift+P)
4174 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4175 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4176 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4178 NewSummon->InitStatsForLevel(petlevel);
4179 NewSummon->InitPetCreateSpells();
4180 NewSummon->InitTalentForLevel();
4182 if(NewSummon->getPetType()==SUMMON_PET)
4184 // Remove Demonic Sacrifice auras (new pet)
4185 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4186 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4188 if((*itr)->GetModifier()->m_miscvalue==2228)
4190 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4191 itr = auraClassScripts.begin();
4193 else
4194 ++itr;
4197 // generate new name for summon pet
4198 std::string new_name=objmgr.GeneratePetName(petentry);
4199 if(!new_name.empty())
4200 NewSummon->SetName(new_name);
4202 else if(NewSummon->getPetType()==HUNTER_PET)
4203 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4205 NewSummon->AIM_Initialize();
4206 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4207 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4209 map->Add((Creature*)NewSummon);
4211 m_caster->SetPet(NewSummon);
4212 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4214 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4216 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4217 ((Player*)m_caster)->PetSpellInitialize();
4221 void Spell::EffectLearnPetSpell(uint32 i)
4223 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4224 return;
4226 Player *_player = (Player*)m_caster;
4228 Pet *pet = _player->GetPet();
4229 if(!pet)
4230 return;
4231 if(!pet->isAlive())
4232 return;
4234 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4235 if(!learn_spellproto)
4236 return;
4238 pet->learnSpell(learn_spellproto->Id);
4240 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4241 _player->PetSpellInitialize();
4244 void Spell::EffectTaunt(uint32 /*i*/)
4246 // this effect use before aura Taunt apply for prevent taunt already attacking target
4247 // for spell as marked "non effective at already attacking target"
4248 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4250 if(unitTarget->getVictim()==m_caster)
4252 SendCastResult(SPELL_FAILED_DONT_REPORT);
4253 return;
4257 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4258 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4259 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4262 void Spell::EffectWeaponDmg(uint32 i)
4264 if(!unitTarget)
4265 return;
4266 if(!unitTarget->isAlive())
4267 return;
4269 // multiple weapon dmg effect workaround
4270 // execute only the last weapon damage
4271 // and handle all effects at once
4272 for (int j = 0; j < 3; j++)
4274 switch(m_spellInfo->Effect[j])
4276 case SPELL_EFFECT_WEAPON_DAMAGE:
4277 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4278 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4279 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4280 if (j < i) // we must calculate only at last weapon effect
4281 return;
4282 break;
4286 // some spell specific modifiers
4287 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4289 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4290 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4291 bool normalized = false;
4293 int32 spell_bonus = 0; // bonus specific for spell
4294 switch(m_spellInfo->SpellFamilyName)
4296 case SPELLFAMILY_WARRIOR:
4298 // Whirlwind, single only spell with 2 weapon white damage apply if have
4299 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4301 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4302 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4304 // Devastate bonus and sunder armor refresh
4305 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4307 uint32 stack = 0;
4308 // Need refresh all Sunder Armor auras from this caster
4309 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4310 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4312 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4313 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4314 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4315 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4317 (*itr).second->RefreshAura();
4318 stack = (*itr).second->GetStackAmount();
4321 if (stack)
4322 spell_bonus += stack * CalculateDamage(2, unitTarget);
4324 break;
4326 case SPELLFAMILY_ROGUE:
4328 // Mutilate (for each hand)
4329 if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4331 bool found = false;
4332 // fast check
4333 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4334 found = true;
4335 // full aura scan
4336 else
4338 Unit::AuraMap const& auras = unitTarget->GetAuras();
4339 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4341 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4343 found = true;
4344 break;
4349 if(found)
4350 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4352 break;
4354 case SPELLFAMILY_PALADIN:
4356 // Seal of Command - receive benefit from Spell Damage and Healing
4357 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4359 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4360 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4361 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4363 break;
4365 case SPELLFAMILY_SHAMAN:
4367 // Skyshatter Harness item set bonus
4368 // Stormstrike
4369 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4371 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4372 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4374 // Stormstrike AP Buff
4375 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4377 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4378 break;
4385 int32 fixed_bonus = 0;
4386 for (int j = 0; j < 3; j++)
4388 switch(m_spellInfo->Effect[j])
4390 case SPELL_EFFECT_WEAPON_DAMAGE:
4391 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4392 fixed_bonus += CalculateDamage(j,unitTarget);
4393 break;
4394 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4395 fixed_bonus += CalculateDamage(j,unitTarget);
4396 normalized = true;
4397 break;
4398 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4399 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4401 // applied only to prev.effects fixed damage
4402 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4403 break;
4404 default:
4405 break; // not weapon damage effect, just skip
4409 // apply weaponDamagePercentMod to spell bonus also
4410 if(spellBonusNeedWeaponDamagePercentMod)
4411 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4413 // non-weapon damage
4414 int32 bonus = spell_bonus + fixed_bonus;
4416 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4417 if(bonus)
4419 UnitMods unitMod;
4420 switch(m_attackType)
4422 default:
4423 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4424 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4425 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4428 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4429 bonus = int32(bonus*weapon_total_pct);
4432 // + weapon damage with applied weapon% dmg to base weapon damage in call
4433 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4435 // total damage
4436 bonus = int32(bonus*totalDamagePercentMod);
4438 // prevent negative damage
4439 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4441 // Add melee damage bonuses (also check for negative)
4442 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4443 m_damage+= eff_damage;
4445 // Hemorrhage
4446 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4448 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4449 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4452 // Mangle (Cat): CP
4453 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4455 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4456 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4459 // take ammo
4460 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4462 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4464 // wands don't have ammo
4465 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4466 return;
4468 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4470 if(pItem->GetMaxStackCount()==1)
4472 // decrease durability for non-stackable throw weapon
4473 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4475 else
4477 // decrease items amount for stackable throw weapon
4478 uint32 count = 1;
4479 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4482 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4483 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4487 void Spell::EffectThreat(uint32 /*i*/)
4489 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4490 return;
4492 if(!unitTarget->CanHaveThreatList())
4493 return;
4495 unitTarget->AddThreat(m_caster, float(damage));
4498 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4500 if(!unitTarget)
4501 return;
4502 if(!unitTarget->isAlive())
4503 return;
4505 uint32 heal = m_caster->GetMaxHealth();
4507 m_healing+=heal;
4510 void Spell::EffectInterruptCast(uint32 /*i*/)
4512 if(!unitTarget)
4513 return;
4514 if(!unitTarget->isAlive())
4515 return;
4517 // TODO: not all spells that used this effect apply cooldown at school spells
4518 // also exist case: apply cooldown to interrupted cast only and to all spells
4519 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4521 if (unitTarget->m_currentSpells[i])
4523 // check if we can interrupt spell
4524 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4526 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4527 unitTarget->InterruptSpell(i,false);
4533 void Spell::EffectSummonObjectWild(uint32 i)
4535 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4537 GameObject* pGameObj = new GameObject;
4539 WorldObject* target = focusObject;
4540 if( !target )
4541 target = m_caster;
4543 float x,y,z;
4544 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4546 x = m_targets.m_destX;
4547 y = m_targets.m_destY;
4548 z = m_targets.m_destZ;
4550 else
4551 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4553 Map *map = target->GetMap();
4555 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4556 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
4558 delete pGameObj;
4559 return;
4562 int32 duration = GetSpellDuration(m_spellInfo);
4563 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4564 pGameObj->SetSpellId(m_spellInfo->Id);
4566 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4567 m_caster->AddGameObject(pGameObj);
4568 map->Add(pGameObj);
4570 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4572 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4574 Player *pl = (Player*)m_caster;
4575 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4576 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4578 uint32 team = ALLIANCE;
4580 if(pl->GetTeam() == team)
4581 team = HORDE;
4583 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4588 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4590 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4592 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4593 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4595 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4600 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4602 GameObject* linkedGO = new GameObject;
4603 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4604 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
4606 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4607 linkedGO->SetSpellId(m_spellInfo->Id);
4609 m_caster->AddGameObject(linkedGO);
4610 map->Add(linkedGO);
4612 else
4614 delete linkedGO;
4615 linkedGO = NULL;
4616 return;
4621 void Spell::EffectScriptEffect(uint32 effIndex)
4623 // TODO: we must implement hunter pet summon at login there (spell 6962)
4625 switch(m_spellInfo->SpellFamilyName)
4627 case SPELLFAMILY_GENERIC:
4629 switch(m_spellInfo->Id)
4631 // PX-238 Winter Wondervolt TRAP
4632 case 26275:
4634 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4636 // check presence
4637 for(int j = 0; j < 4; ++j)
4638 if(unitTarget->HasAura(spells[j],0))
4639 return;
4641 // select spell
4642 uint32 iTmpSpellId = spells[urand(0,3)];
4644 // cast
4645 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4646 return;
4648 // Bending Shinbone
4649 case 8856:
4651 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4652 return;
4654 uint32 spell_id = 0;
4655 switch(urand(1,5))
4657 case 1: spell_id = 8854; break;
4658 default: spell_id = 8855; break;
4661 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4662 return;
4664 // Brittle Armor - need remove one 24575 Brittle Armor aura
4665 case 24590:
4666 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4667 return;
4668 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4669 case 26465:
4670 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4671 return;
4672 // Orb teleport spells
4673 case 25140:
4674 case 25143:
4675 case 25650:
4676 case 25652:
4677 case 29128:
4678 case 29129:
4679 case 35376:
4680 case 35727:
4682 if(!unitTarget)
4683 return;
4685 uint32 spellid;
4686 switch(m_spellInfo->Id)
4688 case 25140: spellid = 32571; break;
4689 case 25143: spellid = 32572; break;
4690 case 25650: spellid = 30140; break;
4691 case 25652: spellid = 30141; break;
4692 case 29128: spellid = 32568; break;
4693 case 29129: spellid = 32569; break;
4694 case 35376: spellid = 25649; break;
4695 case 35727: spellid = 35730; break;
4696 default:
4697 return;
4700 unitTarget->CastSpell(unitTarget,spellid,false);
4701 return;
4703 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4704 case 22539:
4705 case 22972:
4706 case 22975:
4707 case 22976:
4708 case 22977:
4709 case 22978:
4710 case 22979:
4711 case 22980:
4712 case 22981:
4713 case 22982:
4714 case 22983:
4715 case 22984:
4716 case 22985:
4718 if(!unitTarget || !unitTarget->isAlive())
4719 return;
4721 // Onyxia Scale Cloak
4722 if(unitTarget->GetDummyAura(22683))
4723 return;
4725 // Shadow Flame
4726 m_caster->CastSpell(unitTarget, 22682, true);
4727 return;
4729 // Summon Black Qiraji Battle Tank
4730 case 26656:
4732 if(!unitTarget)
4733 return;
4735 // Prevent stacking of mounts
4736 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4738 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4739 if (unitTarget->GetAreaId() == 3428)
4740 unitTarget->CastSpell(unitTarget, 25863, false);
4741 else
4742 unitTarget->CastSpell(unitTarget, 26655, false);
4743 return;
4745 // Piccolo of the Flaming Fire
4746 case 17512:
4748 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4749 return;
4750 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4751 return;
4753 // Escape artist
4754 case 20589:
4756 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4757 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4758 return;
4760 // Mirren's Drinking Hat
4761 case 29830:
4763 uint32 item = 0;
4764 switch ( urand(1,6) )
4766 case 1:case 2:case 3:
4767 item = 23584;break; // Loch Modan Lager
4768 case 4:case 5:
4769 item = 23585;break; // Stouthammer Lite
4770 case 6:
4771 item = 23586;break; // Aerie Peak Pale Ale
4773 if (item)
4774 DoCreateItem(effIndex,item);
4775 break;
4777 // Improved Sprint
4778 case 30918:
4780 // Removes snares and roots.
4781 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4782 Unit::AuraMap& Auras = unitTarget->GetAuras();
4783 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4785 next = iter;
4786 ++next;
4787 Aura *aur = iter->second;
4788 if (!aur->IsPositive()) //only remove negative spells
4790 // check for mechanic mask
4791 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4793 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4794 if(Auras.empty())
4795 break;
4796 else
4797 next = Auras.begin();
4801 break;
4803 // Flame Crash
4804 case 41126:
4806 if(!unitTarget)
4807 return;
4809 unitTarget->CastSpell(unitTarget, 41131, true);
4810 break;
4812 // Force Cast - Portal Effect: Sunwell Isle
4813 case 44876:
4815 if(!unitTarget)
4816 return;
4818 unitTarget->CastSpell(unitTarget, 44870, true);
4819 break;
4821 // Goblin Weather Machine
4822 case 46203:
4824 if(!unitTarget)
4825 return;
4827 uint32 spellId;
4828 switch(rand()%4)
4830 case 0: spellId = 46740; break;
4831 case 1: spellId = 46739; break;
4832 case 2: spellId = 46738; break;
4833 case 3: spellId = 46736; break;
4835 unitTarget->CastSpell(unitTarget, spellId, true);
4836 break;
4838 //5,000 Gold
4839 case 46642:
4841 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4842 return;
4844 ((Player*)unitTarget)->ModifyMoney(50000000);
4846 break;
4848 // Emblazon Runeblade
4849 case 51770:
4851 if(!unitTarget)
4852 return;
4854 unitTarget->CastSpell(unitTarget,51771,false);
4855 break;
4857 // Death Gate
4858 case 52751:
4860 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4861 return;
4862 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4863 unitTarget->CastSpell(unitTarget, damage, false);
4864 break;
4866 case 58418: // Portal to Orgrimmar
4867 case 58420: // Portal to Stormwind
4869 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
4870 return;
4872 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
4873 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
4875 if( ((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID) )
4876 unitTarget->CastSpell(unitTarget, spellID, true);
4878 return;
4880 // random spell learn instead placeholder
4881 case 60893: // Northrend Alchemy Research
4882 case 61177: // Northrend Inscription Research
4883 case 61288: // Minor Inscription Research
4884 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4886 if(!IsExplicitDiscoverySpell(m_spellInfo))
4888 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4889 return;
4892 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4893 return;
4894 Player* player = (Player*)m_caster;
4896 // need replace effect 0 item by loot
4897 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4899 if(!player->HasItemCount(reagent_id,1))
4900 return;
4902 // remove reagent
4903 uint32 count = 1;
4904 player->DestroyItemCount (reagent_id,count,true);
4906 // create some random items
4907 player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
4909 // learn random explicit discovery recipe (if any)
4910 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4911 player->learnSpell(discoveredSpell,false);
4912 return;
4915 break;
4917 case SPELLFAMILY_WARLOCK:
4919 switch(m_spellInfo->Id)
4921 // Healthstone creating spells
4922 case 6201:
4923 case 6202:
4924 case 5699:
4925 case 11729:
4926 case 11730:
4927 case 27230:
4928 case 47871:
4929 case 47878:
4931 uint32 itemtype;
4932 uint32 rank = 0;
4933 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4934 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4936 if((*i)->GetId() == 18692)
4938 rank = 1;
4939 break;
4941 else if((*i)->GetId() == 18693)
4943 rank = 2;
4944 break;
4948 static uint32 const itypes[8][3] = {
4949 { 5512,19004,19005}, // Minor Healthstone
4950 { 5511,19006,19007}, // Lesser Healthstone
4951 { 5509,19008,19009}, // Healthstone
4952 { 5510,19010,19011}, // Greater Healthstone
4953 { 9421,19012,19013}, // Major Healthstone
4954 {22103,22104,22105}, // Master Healthstone
4955 {36889,36890,36891}, // Demonic Healthstone
4956 {36892,36893,36894} // Fel Healthstone
4959 switch(m_spellInfo->Id)
4961 case 6201:
4962 itemtype=itypes[0][rank];break; // Minor Healthstone
4963 case 6202:
4964 itemtype=itypes[1][rank];break; // Lesser Healthstone
4965 case 5699:
4966 itemtype=itypes[2][rank];break; // Healthstone
4967 case 11729:
4968 itemtype=itypes[3][rank];break; // Greater Healthstone
4969 case 11730:
4970 itemtype=itypes[4][rank];break; // Major Healthstone
4971 case 27230:
4972 itemtype=itypes[5][rank];break; // Master Healthstone
4973 case 47871:
4974 itemtype=itypes[6][rank];break; // Demonic Healthstone
4975 case 47878:
4976 itemtype=itypes[7][rank];break; // Fel Healthstone
4977 default:
4978 return;
4980 DoCreateItem( effIndex, itemtype );
4981 return;
4984 break;
4986 case SPELLFAMILY_PRIEST:
4988 switch(m_spellInfo->Id)
4990 // Pain and Suffering
4991 case 47948:
4993 if (!unitTarget)
4994 return;
4995 // Refresh Shadow Word: Pain on target
4996 Unit::AuraMap& auras = unitTarget->GetAuras();
4997 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
4999 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5000 if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5001 spellInfo->SpellFamilyFlags & 0x0000000000008000LL &&
5002 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5004 (*itr).second->RefreshAura();
5005 return;
5008 return;
5010 default:
5011 break;
5013 break;
5015 case SPELLFAMILY_HUNTER:
5017 switch(m_spellInfo->Id)
5019 // Chimera Shot
5020 case 53209:
5022 uint32 spellId = 0;
5023 int32 basePoint = 0;
5024 Unit::AuraMap& Auras = unitTarget->GetAuras();
5025 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5027 Aura *aura = (*i).second;
5028 if (aura->GetCasterGUID() != m_caster->GetGUID())
5029 continue;
5030 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5031 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5032 if (!(familyFlag & 0x000000800000C000LL))
5033 continue;
5034 // Refresh aura duration
5035 aura->RefreshAura();
5037 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5038 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
5040 spellId = 53353; // 53353 Chimera Shot - Serpent
5041 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5043 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5044 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
5046 spellId = 53358; // 53358 Chimera Shot - Viper
5047 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5049 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5050 if (familyFlag & 0x0000000000008000LL)
5051 spellId = 53359; // 53359 Chimera Shot - Scorpid
5052 // ?? nothing say in spell desc (possibly need addition check)
5053 //if (familyFlag & 0x0000010000000000LL || // dot
5054 // familyFlag & 0x0000100000000000LL) // stun
5056 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5059 if (spellId)
5060 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5061 return;
5063 default:
5064 break;
5066 break;
5068 case SPELLFAMILY_PALADIN:
5070 // Judgement
5071 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
5073 if(!unitTarget || !unitTarget->isAlive())
5074 return;
5075 uint32 spellId1 = 0;
5076 uint32 spellId2 = 0;
5078 // Judgement self add switch
5079 switch (m_spellInfo->Id)
5081 case 41467: break; // Judgement
5082 case 53407: spellId1 = 20184; break; // Judgement of Justice
5083 case 20271: // Judgement of Light
5084 case 57774: spellId1 = 20185; break; // Judgement of Light
5085 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5086 default:
5087 return;
5089 // all seals have aura dummy in 2 effect
5090 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5091 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5093 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5094 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5095 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5096 continue;
5097 spellId2 = (*itr)->GetModifier()->m_amount;
5098 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5099 if (!judge)
5100 continue;
5101 break;
5103 if (spellId1)
5104 m_caster->CastSpell(unitTarget, spellId1, true);
5105 if (spellId2)
5106 m_caster->CastSpell(unitTarget, spellId2, true);
5107 return;
5110 case SPELLFAMILY_POTION:
5112 switch(m_spellInfo->Id)
5114 // Dreaming Glory
5115 case 28698:
5117 if(!unitTarget)
5118 return;
5119 unitTarget->CastSpell(unitTarget, 28694, true);
5120 break;
5122 // Netherbloom
5123 case 28702:
5125 if(!unitTarget)
5126 return;
5127 // 25% chance of casting a random buff
5128 if(roll_chance_i(75))
5129 return;
5131 // triggered spells are 28703 to 28707
5132 // Note: some sources say, that there was the possibility of
5133 // receiving a debuff. However, this seems to be removed by a patch.
5134 const uint32 spellid = 28703;
5136 // don't overwrite an existing aura
5137 for(uint8 i=0; i<5; i++)
5138 if(unitTarget->HasAura(spellid+i, 0))
5139 return;
5140 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5141 break;
5144 // Nightmare Vine
5145 case 28720:
5147 if(!unitTarget)
5148 return;
5149 // 25% chance of casting Nightmare Pollen
5150 if(roll_chance_i(75))
5151 return;
5152 unitTarget->CastSpell(unitTarget, 28721, true);
5153 break;
5156 break;
5160 // normal DB scripted effect
5161 if(!unitTarget)
5162 return;
5164 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5165 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5168 void Spell::EffectSanctuary(uint32 /*i*/)
5170 if(!unitTarget)
5171 return;
5172 //unitTarget->CombatStop();
5174 unitTarget->CombatStop();
5175 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5176 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5177 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5179 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5183 void Spell::EffectAddComboPoints(uint32 /*i*/)
5185 if(!unitTarget)
5186 return;
5188 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5189 return;
5191 if(damage <= 0)
5192 return;
5194 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5197 void Spell::EffectDuel(uint32 i)
5199 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5200 return;
5202 Player *caster = (Player*)m_caster;
5203 Player *target = (Player*)unitTarget;
5205 // caster or target already have requested duel
5206 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5207 return;
5209 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5210 // Don't have to check the target's map since you cannot challenge someone across maps
5211 uint32 mapid = caster->GetMapId();
5212 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5214 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5215 return;
5218 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5219 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5221 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5222 return;
5225 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5226 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5228 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5229 return;
5232 //CREATE DUEL FLAG OBJECT
5233 GameObject* pGameObj = new GameObject;
5235 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5237 Map *map = m_caster->GetMap();
5238 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5239 map, m_caster->GetPhaseMask(),
5240 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5241 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5242 m_caster->GetPositionZ(),
5243 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1))
5245 delete pGameObj;
5246 return;
5249 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5250 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5251 int32 duration = GetSpellDuration(m_spellInfo);
5252 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5253 pGameObj->SetSpellId(m_spellInfo->Id);
5255 m_caster->AddGameObject(pGameObj);
5256 map->Add(pGameObj);
5257 //END
5259 // Send request
5260 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5261 data << pGameObj->GetGUID();
5262 data << caster->GetGUID();
5263 caster->GetSession()->SendPacket(&data);
5264 target->GetSession()->SendPacket(&data);
5266 // create duel-info
5267 DuelInfo *duel = new DuelInfo;
5268 duel->initiator = caster;
5269 duel->opponent = target;
5270 duel->startTime = 0;
5271 duel->startTimer = 0;
5272 caster->duel = duel;
5274 DuelInfo *duel2 = new DuelInfo;
5275 duel2->initiator = caster;
5276 duel2->opponent = caster;
5277 duel2->startTime = 0;
5278 duel2->startTimer = 0;
5279 target->duel = duel2;
5281 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5282 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5285 void Spell::EffectStuck(uint32 /*i*/)
5287 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5288 return;
5290 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5291 return;
5293 Player* pTarget = (Player*)unitTarget;
5295 sLog.outDebug("Spell Effect: Stuck");
5296 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());
5298 if(pTarget->isInFlight())
5299 return;
5301 // homebind location is loaded always
5302 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5304 // Stuck spell trigger Hearthstone cooldown
5305 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5306 if(!spellInfo)
5307 return;
5308 Spell spell(pTarget,spellInfo,true,0);
5309 spell.SendSpellCooldown();
5312 void Spell::EffectSummonPlayer(uint32 /*i*/)
5314 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5315 return;
5317 // Evil Twin (ignore player summon, but hide this for summoner)
5318 if(unitTarget->GetDummyAura(23445))
5319 return;
5321 float x,y,z;
5322 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5324 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5326 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5327 data << uint64(m_caster->GetGUID()); // summoner guid
5328 data << uint32(m_caster->GetZoneId()); // summoner zone
5329 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5330 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5333 static ScriptInfo generateActivateCommand()
5335 ScriptInfo si;
5336 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5337 return si;
5340 void Spell::EffectActivateObject(uint32 effect_idx)
5342 if(!gameObjTarget)
5343 return;
5345 static ScriptInfo activateCommand = generateActivateCommand();
5347 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5349 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5352 void Spell::EffectApplyGlyph(uint32 i)
5354 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5355 return;
5357 Player *player = (Player*)m_caster;
5359 // apply new one
5360 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5362 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5364 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5366 if(gp->TypeFlags != gs->TypeFlags)
5368 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5369 return; // glyph slot mismatch
5373 // remove old glyph
5374 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5376 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5378 player->RemoveAurasDueToSpell(old_gp->SpellId);
5379 player->SetGlyph(m_glyphIndex, 0);
5383 player->CastSpell(m_caster, gp->SpellId, true);
5384 player->SetGlyph(m_glyphIndex, glyph);
5389 void Spell::EffectSummonTotem(uint32 i)
5391 uint8 slot = 0;
5392 switch(m_spellInfo->EffectMiscValueB[i])
5394 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5395 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5396 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5397 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5398 // Battle standard case
5399 case SUMMON_TYPE_TOTEM: slot = 254; break;
5400 // jewelery statue case, like totem without slot
5401 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5402 default: return;
5405 if(slot < MAX_TOTEM)
5407 uint64 guid = m_caster->m_TotemSlot[slot];
5408 if(guid != 0)
5410 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5411 if(OldTotem && OldTotem->isTotem())
5412 ((Totem*)OldTotem)->UnSummon();
5416 uint32 team = 0;
5417 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5418 team = ((Player*)m_caster)->GetTeam();
5420 Totem* pTotem = new Totem;
5422 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5423 m_spellInfo->EffectMiscValue[i], team ))
5425 delete pTotem;
5426 return;
5429 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5431 float x,y,z;
5432 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5434 // totem must be at same Z in case swimming caster and etc.
5435 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5436 z = m_caster->GetPositionZ();
5438 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5440 if(slot < MAX_TOTEM)
5441 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5443 pTotem->SetOwner(m_caster->GetGUID());
5444 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5446 int32 duration=GetSpellDuration(m_spellInfo);
5447 if(Player* modOwner = m_caster->GetSpellModOwner())
5448 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5449 pTotem->SetDuration(duration);
5451 if (damage) // if not spell info, DB values used
5453 pTotem->SetMaxHealth(damage);
5454 pTotem->SetHealth(damage);
5457 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5459 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5460 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5462 pTotem->Summon(m_caster);
5464 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5466 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5467 data << uint8(slot);
5468 data << uint64(pTotem->GetGUID());
5469 data << uint32(duration);
5470 data << uint32(m_spellInfo->Id);
5471 ((Player*)m_caster)->SendDirectMessage(&data);
5475 void Spell::EffectEnchantHeldItem(uint32 i)
5477 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5478 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5479 return;
5481 Player* item_owner = (Player*)unitTarget;
5482 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5484 if(!item )
5485 return;
5487 // must be equipped
5488 if(!item ->IsEquipped())
5489 return;
5491 if (m_spellInfo->EffectMiscValue[i])
5493 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5494 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5495 if(!duration)
5496 duration = m_currentBasePoints[i]+1; //Base points after ..
5497 if(!duration)
5498 duration = 10; //10 seconds for enchants which don't have listed duration
5500 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5501 if(!pEnchant)
5502 return;
5504 // Always go to temp enchantment slot
5505 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5507 // Enchantment will not be applied if a different one already exists
5508 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5509 return;
5511 // Apply the temporary enchantment
5512 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5513 item_owner->ApplyEnchantment(item,slot,true);
5517 void Spell::EffectDisEnchant(uint32 /*i*/)
5519 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5520 return;
5522 Player* p_caster = (Player*)m_caster;
5523 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5524 return;
5526 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5528 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5530 // item will be removed at disenchanting end
5533 void Spell::EffectInebriate(uint32 /*i*/)
5535 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5536 return;
5538 Player *player = (Player*)unitTarget;
5539 uint16 currentDrunk = player->GetDrunkValue();
5540 uint16 drunkMod = damage * 256;
5541 if (currentDrunk + drunkMod > 0xFFFF)
5542 currentDrunk = 0xFFFF;
5543 else
5544 currentDrunk += drunkMod;
5545 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5548 void Spell::EffectFeedPet(uint32 i)
5550 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5551 return;
5553 Player *_player = (Player*)m_caster;
5555 Item* foodItem = m_targets.getItemTarget();
5556 if(!foodItem)
5557 return;
5559 Pet *pet = _player->GetPet();
5560 if(!pet)
5561 return;
5563 if(!pet->isAlive())
5564 return;
5566 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5567 if(benefit <= 0)
5568 return;
5570 uint32 count = 1;
5571 _player->DestroyItemCount(foodItem,count,true);
5572 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5574 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5577 void Spell::EffectDismissPet(uint32 /*i*/)
5579 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5580 return;
5582 Pet* pet = m_caster->GetPet();
5584 // not let dismiss dead pet
5585 if(!pet||!pet->isAlive())
5586 return;
5588 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5591 void Spell::EffectSummonObject(uint32 i)
5593 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5595 uint8 slot = 0;
5596 switch(m_spellInfo->Effect[i])
5598 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5599 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5600 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5601 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5602 default: return;
5605 uint64 guid = m_caster->m_ObjectSlot[slot];
5606 if(guid != 0)
5608 GameObject* obj = NULL;
5609 if( m_caster )
5610 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5612 if(obj) obj->Delete();
5613 m_caster->m_ObjectSlot[slot] = 0;
5616 GameObject* pGameObj = new GameObject;
5618 float x,y,z;
5619 // If dest location if present
5620 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5622 x = m_targets.m_destX;
5623 y = m_targets.m_destY;
5624 z = m_targets.m_destZ;
5626 // Summon in random point all other units if location present
5627 else
5628 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5630 Map *map = m_caster->GetMap();
5631 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5632 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1))
5634 delete pGameObj;
5635 return;
5638 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5639 int32 duration = GetSpellDuration(m_spellInfo);
5640 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5641 pGameObj->SetSpellId(m_spellInfo->Id);
5642 m_caster->AddGameObject(pGameObj);
5644 map->Add(pGameObj);
5645 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5646 data << pGameObj->GetGUID();
5647 m_caster->SendMessageToSet(&data,true);
5649 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5652 void Spell::EffectResurrect(uint32 /*effIndex*/)
5654 if(!unitTarget)
5655 return;
5656 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5657 return;
5659 if(unitTarget->isAlive())
5660 return;
5661 if(!unitTarget->IsInWorld())
5662 return;
5664 switch (m_spellInfo->Id)
5666 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5667 case 8342:
5668 if (roll_chance_i(67))
5670 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5671 return;
5673 break;
5674 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5675 case 22999:
5676 if (roll_chance_i(50))
5678 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5679 return;
5681 break;
5682 default:
5683 break;
5686 Player* pTarget = ((Player*)unitTarget);
5688 if(pTarget->isRessurectRequested()) // already have one active request
5689 return;
5691 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5692 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5694 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5695 SendResurrectRequest(pTarget);
5698 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5700 if(!unitTarget || !unitTarget->isAlive())
5701 return;
5703 if( unitTarget->m_extraAttacks )
5704 return;
5706 unitTarget->m_extraAttacks = damage;
5709 void Spell::EffectParry(uint32 /*i*/)
5711 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5712 ((Player*)unitTarget)->SetCanParry(true);
5715 void Spell::EffectBlock(uint32 /*i*/)
5717 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5718 ((Player*)unitTarget)->SetCanBlock(true);
5721 void Spell::EffectMomentMove(uint32 i)
5723 if(unitTarget->isInFlight())
5724 return;
5726 if( m_spellInfo->rangeIndex== 1) //self range
5728 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5730 // before caster
5731 float fx,fy,fz;
5732 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5733 float ox,oy,oz;
5734 unitTarget->GetPosition(ox,oy,oz);
5736 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5737 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5739 fx = fx2;
5740 fy = fy2;
5741 fz = fz2;
5742 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5745 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(),unitTarget==m_caster);
5749 void Spell::EffectReputation(uint32 i)
5751 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5752 return;
5754 Player *_player = (Player*)unitTarget;
5756 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5758 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5760 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5762 if(!factionEntry)
5763 return;
5765 _player->GetReputationMgr().ModifyReputation(factionEntry,rep_change);
5768 void Spell::EffectQuestComplete(uint32 i)
5770 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5771 return;
5773 Player *_player = (Player*)m_caster;
5775 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5776 _player->AreaExploredOrEventHappens(quest_id);
5779 void Spell::EffectSelfResurrect(uint32 i)
5781 if(!unitTarget || unitTarget->isAlive())
5782 return;
5783 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5784 return;
5785 if(!unitTarget->IsInWorld())
5786 return;
5788 uint32 health = 0;
5789 uint32 mana = 0;
5791 // flat case
5792 if(damage < 0)
5794 health = uint32(-damage);
5795 mana = m_spellInfo->EffectMiscValue[i];
5797 // percent case
5798 else
5800 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5801 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5802 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5805 Player *plr = ((Player*)unitTarget);
5806 plr->ResurrectPlayer(0.0f);
5808 plr->SetHealth( health );
5809 plr->SetPower(POWER_MANA, mana );
5810 plr->SetPower(POWER_RAGE, 0 );
5811 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5813 plr->SpawnCorpseBones();
5815 plr->SaveToDB();
5818 void Spell::EffectSkinning(uint32 /*i*/)
5820 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5821 return;
5822 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5823 return;
5825 Creature* creature = (Creature*) unitTarget;
5826 int32 targetLevel = creature->getLevel();
5828 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5830 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5831 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5833 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5835 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5837 // Double chances for elites
5838 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5841 void Spell::EffectCharge(uint32 /*i*/)
5843 if(!unitTarget || !m_caster)
5844 return;
5846 float x, y, z;
5847 unitTarget->GetContactPoint(m_caster, x, y, z);
5848 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5849 ((Creature *)unitTarget)->StopMoving();
5851 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5852 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5854 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5855 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5857 // not all charge effects used in negative spells
5858 if ( !IsPositiveSpell(m_spellInfo->Id))
5859 m_caster->Attack(unitTarget,true);
5862 void Spell::EffectSummonCritter(uint32 i)
5864 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5865 return;
5866 Player* player = (Player*)m_caster;
5868 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5869 if(!pet_entry)
5870 return;
5872 Pet* old_critter = player->GetMiniPet();
5874 // for same pet just despawn
5875 if(old_critter && old_critter->GetEntry() == pet_entry)
5877 player->RemoveMiniPet();
5878 return;
5881 // despawn old pet before summon new
5882 if(old_critter)
5883 player->RemoveMiniPet();
5885 // summon new pet
5886 Pet* critter = new Pet(MINI_PET);
5888 Map *map = m_caster->GetMap();
5889 uint32 pet_number = objmgr.GeneratePetNumber();
5890 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5891 pet_entry, pet_number))
5893 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5894 delete critter;
5895 return;
5898 float x,y,z;
5899 // If dest location if present
5900 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5902 x = m_targets.m_destX;
5903 y = m_targets.m_destY;
5904 z = m_targets.m_destZ;
5906 // Summon if dest location not present near caster
5907 else
5908 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5910 critter->Relocate(x,y,z,m_caster->GetOrientation());
5912 if(!critter->IsPositionValid())
5914 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5915 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5916 delete critter;
5917 return;
5920 critter->SetOwnerGUID(m_caster->GetGUID());
5921 critter->SetCreatorGUID(m_caster->GetGUID());
5922 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5923 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5925 critter->AIM_Initialize();
5926 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5927 critter->SetMaxHealth(1);
5928 critter->SetHealth(1);
5929 critter->SetLevel(1);
5931 // set timer for unsummon
5932 int32 duration = GetSpellDuration(m_spellInfo);
5933 if(duration > 0)
5934 critter->SetDuration(duration);
5936 std::string name = player->GetName();
5937 name.append(petTypeSuffix[critter->getPetType()]);
5938 critter->SetName( name );
5939 player->SetMiniPet(critter);
5941 map->Add((Creature*)critter);
5944 void Spell::EffectKnockBack(uint32 i)
5946 if(!unitTarget || !m_caster)
5947 return;
5949 // Effect only works on players
5950 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5951 return;
5953 float vsin = sin(m_caster->GetAngle(unitTarget));
5954 float vcos = cos(m_caster->GetAngle(unitTarget));
5956 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5957 data.append(unitTarget->GetPackGUID());
5958 data << uint32(0); // Sequence
5959 data << float(vcos); // x direction
5960 data << float(vsin); // y direction
5961 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5962 data << float(damage/-10); // Z Movement speed (vertical)
5964 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5967 void Spell::EffectSendTaxi(uint32 i)
5969 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5970 return;
5972 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5973 if(!entry)
5974 return;
5976 std::vector<uint32> nodes;
5978 nodes.resize(2);
5979 nodes[0] = entry->from;
5980 nodes[1] = entry->to;
5982 uint32 mountid = 0;
5983 switch(m_spellInfo->Id)
5985 case 31606: //Stormcrow Amulet
5986 mountid = 17447;
5987 break;
5988 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5989 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5990 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5991 mountid = 22840;
5992 break;
5993 case 34905: //Stealth Flight
5994 mountid = 6851;
5995 break;
5996 case 45883: //Amber Ledge to Beryl Point
5997 mountid = 23524;
5998 break;
5999 case 46064: //Amber Ledge to Coldarra
6000 mountid = 6371;
6001 break;
6002 case 53335: //Stormwind Harbor Flight - Peaceful
6003 mountid = 6852;
6004 break;
6007 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
6011 void Spell::EffectPlayerPull(uint32 i)
6013 if(!unitTarget || !m_caster)
6014 return;
6016 // Effect only works on players
6017 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6018 return;
6020 float vsin = sin(unitTarget->GetAngle(m_caster));
6021 float vcos = cos(unitTarget->GetAngle(m_caster));
6023 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
6024 data.append(unitTarget->GetPackGUID());
6025 data << uint32(0); // Sequence
6026 data << float(vcos); // x direction
6027 data << float(vsin); // y direction
6028 // Horizontal speed
6029 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6030 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6032 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6035 void Spell::EffectDispelMechanic(uint32 i)
6037 if(!unitTarget)
6038 return;
6040 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6042 Unit::AuraMap& Auras = unitTarget->GetAuras();
6043 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6045 next = iter;
6046 ++next;
6047 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6048 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6050 unitTarget->RemoveAurasDueToSpell(spell->Id);
6051 if(Auras.empty())
6052 break;
6053 else
6054 next = Auras.begin();
6057 return;
6060 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6062 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6063 return;
6064 Player *_player = (Player*)m_caster;
6065 Pet *pet = _player->GetPet();
6066 if(!pet)
6067 return;
6068 if(pet->isAlive())
6069 return;
6070 if(damage < 0)
6071 return;
6072 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6073 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6074 pet->setDeathState( ALIVE );
6075 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6076 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6078 pet->AIM_Initialize();
6080 _player->PetSpellInitialize();
6081 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6084 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6086 float mana = 0;
6087 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6089 if(!m_caster->m_TotemSlot[slot])
6090 continue;
6092 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
6093 if(totem && totem->isTotem())
6095 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6096 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6097 if(spellInfo)
6098 mana += spellInfo->manaCost * damage / 100;
6099 ((Totem*)totem)->UnSummon();
6103 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6104 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6107 void Spell::EffectDurabilityDamage(uint32 i)
6109 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6110 return;
6112 int32 slot = m_spellInfo->EffectMiscValue[i];
6114 // FIXME: some spells effects have value -1/-2
6115 // Possibly its mean -1 all player equipped items and -2 all items
6116 if(slot < 0)
6118 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6119 return;
6122 // invalid slot value
6123 if(slot >= INVENTORY_SLOT_BAG_END)
6124 return;
6126 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6127 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6130 void Spell::EffectDurabilityDamagePCT(uint32 i)
6132 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6133 return;
6135 int32 slot = m_spellInfo->EffectMiscValue[i];
6137 // FIXME: some spells effects have value -1/-2
6138 // Possibly its mean -1 all player equipped items and -2 all items
6139 if(slot < 0)
6141 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6142 return;
6145 // invalid slot value
6146 if(slot >= INVENTORY_SLOT_BAG_END)
6147 return;
6149 if(damage <= 0)
6150 return;
6152 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6153 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6156 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6158 if(!unitTarget)
6159 return;
6161 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6164 void Spell::EffectTransmitted(uint32 effIndex)
6166 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6168 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6170 if (!goinfo)
6172 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6173 return;
6176 float fx,fy,fz;
6178 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6180 fx = m_targets.m_destX;
6181 fy = m_targets.m_destY;
6182 fz = m_targets.m_destZ;
6184 //FIXME: this can be better check for most objects but still hack
6185 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6187 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6188 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6190 else
6192 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6193 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6194 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6196 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6199 Map *cMap = m_caster->GetMap();
6201 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6203 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6204 { // but this is not proper, we really need to ignore not materialized objects
6205 SendCastResult(SPELL_FAILED_NOT_HERE);
6206 SendChannelUpdate(0);
6207 return;
6210 // replace by water level in this case
6211 fz = cMap->GetWaterLevel(fx,fy);
6213 // if gameobject is summoning object, it should be spawned right on caster's position
6214 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6216 m_caster->GetPosition(fx,fy,fz);
6219 GameObject* pGameObj = new GameObject;
6221 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6222 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
6224 delete pGameObj;
6225 return;
6228 int32 duration = GetSpellDuration(m_spellInfo);
6230 switch(goinfo->type)
6232 case GAMEOBJECT_TYPE_FISHINGNODE:
6234 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6235 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6237 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6238 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6239 int32 lastSec;
6240 switch(urand(0, 3))
6242 case 0: lastSec = 3; break;
6243 case 1: lastSec = 7; break;
6244 case 2: lastSec = 13; break;
6245 case 3: lastSec = 17; break;
6248 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6249 break;
6251 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6253 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6255 pGameObj->AddUniqueUse((Player*)m_caster);
6256 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6258 break;
6260 case GAMEOBJECT_TYPE_FISHINGHOLE:
6261 case GAMEOBJECT_TYPE_CHEST:
6262 default:
6264 break;
6268 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6270 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6272 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6273 pGameObj->SetSpellId(m_spellInfo->Id);
6275 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6276 //m_caster->AddGameObject(pGameObj);
6277 //m_ObjToDel.push_back(pGameObj);
6279 cMap->Add(pGameObj);
6281 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6282 data << uint64(pGameObj->GetGUID());
6283 m_caster->SendMessageToSet(&data,true);
6285 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6287 GameObject* linkedGO = new GameObject;
6288 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6289 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
6291 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6292 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6293 linkedGO->SetSpellId(m_spellInfo->Id);
6294 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6296 linkedGO->GetMap()->Add(linkedGO);
6298 else
6300 delete linkedGO;
6301 linkedGO = NULL;
6302 return;
6307 void Spell::EffectProspecting(uint32 /*i*/)
6309 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6310 return;
6312 Player* p_caster = (Player*)m_caster;
6313 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6314 return;
6316 if(itemTarget->GetCount() < 5)
6317 return;
6319 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6321 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6322 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6323 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6326 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6329 void Spell::EffectMilling(uint32 /*i*/)
6331 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6332 return;
6334 Player* p_caster = (Player*)m_caster;
6335 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6336 return;
6338 if(itemTarget->GetCount() < 5)
6339 return;
6341 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6343 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6344 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6345 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6348 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6351 void Spell::EffectSkill(uint32 /*i*/)
6353 sLog.outDebug("WORLD: SkillEFFECT");
6356 void Spell::EffectSummonDemon(uint32 i)
6358 // select center of summon position
6359 float center_x = m_targets.m_destX;
6360 float center_y = m_targets.m_destY;
6361 float center_z = m_targets.m_destZ;
6363 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6365 int32 amount = damage > 0 ? damage : 1;
6367 for(int32 count = 0; count < amount; ++count)
6369 float px, py, pz;
6370 // If dest location if present
6371 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6373 // Summon 1 unit in dest location
6374 if (count == 0)
6376 px = m_targets.m_destX;
6377 py = m_targets.m_destY;
6378 pz = m_targets.m_destZ;
6380 // Summon in random point all other units if location present
6381 else
6382 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
6384 // Summon if dest location not present near caster
6385 else
6386 m_caster->GetClosePoint(px,py,pz,3.0f);
6388 int32 duration = GetSpellDuration(m_spellInfo);
6390 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
6391 if (!Charmed) // something fatal, not attempt more
6392 return;
6394 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6395 Charmed->SetLevel(m_caster->getLevel());
6397 // TODO: Add damage/mana/hp according to level
6399 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6401 // Enslave demon effect, without mana cost and cooldown
6402 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6404 // Inferno effect
6405 Charmed->CastSpell(Charmed, 22703, true, 0);
6410 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6411 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6412 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6413 This is why we use a half sec delay between the visual effect and the resurrection itself */
6414 void Spell::EffectSpiritHeal(uint32 /*i*/)
6417 if(!unitTarget || unitTarget->isAlive())
6418 return;
6419 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6420 return;
6421 if(!unitTarget->IsInWorld())
6422 return;
6424 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6425 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6426 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6427 ((Player*)unitTarget)->SpawnCorpseBones();
6431 // remove insignia spell effect
6432 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6434 sLog.outDebug("Effect: SkinPlayerCorpse");
6435 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6436 return;
6438 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6441 void Spell::EffectStealBeneficialBuff(uint32 i)
6443 sLog.outDebug("Effect: StealBeneficialBuff");
6445 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6446 return;
6448 std::vector <Aura *> steal_list;
6449 // Create dispel mask by dispel type
6450 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6451 Unit::AuraMap const& auras = unitTarget->GetAuras();
6452 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6454 Aura *aur = (*itr).second;
6455 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6457 // Need check for passive? this
6458 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6459 steal_list.push_back(aur);
6462 // Ok if exist some buffs for dispel try dispel it
6463 if (!steal_list.empty())
6465 std::list < std::pair<uint32,uint64> > success_list;
6466 int32 list_size = steal_list.size();
6467 // Dispell N = damage buffs (or while exist buffs for dispel)
6468 for (int32 count=0; count < damage && list_size > 0; ++count)
6470 // Random select buff for dispel
6471 Aura *aur = steal_list[urand(0, list_size-1)];
6472 // Not use chance for steal
6473 // TODO possible need do it
6474 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6476 // Remove buff from list for prevent doubles
6477 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6479 Aura *stealed = *j;
6480 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6482 j = steal_list.erase(j);
6483 --list_size;
6485 else
6486 ++j;
6489 // Really try steal and send log
6490 if (!success_list.empty())
6492 int32 count = success_list.size();
6493 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6494 data.append(unitTarget->GetPackGUID()); // Victim GUID
6495 data.append(m_caster->GetPackGUID()); // Caster GUID
6496 data << uint32(m_spellInfo->Id); // Dispell spell id
6497 data << uint8(0); // not used
6498 data << uint32(count); // count
6499 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6501 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6502 data << uint32(spellInfo->Id); // Spell Id
6503 data << uint8(0); // 0 - steals !=0 transfers
6504 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6506 m_caster->SendMessageToSet(&data, true);
6511 void Spell::EffectKillCredit(uint32 i)
6513 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6514 return;
6516 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6519 void Spell::EffectQuestFail(uint32 i)
6521 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6522 return;
6524 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6527 void Spell::EffectActivateRune(uint32 eff_idx)
6529 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6530 return;
6532 Player *plr = (Player*)m_caster;
6534 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6535 return;
6537 for(uint32 j = 0; j < MAX_RUNES; ++j)
6539 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6541 plr->SetRuneCooldown(j, 0);
6546 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6548 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6549 ((Player*)unitTarget)->SetCanTitanGrip(true);
6552 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6554 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6555 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6556 return;
6558 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);