[9153] Use in code heal amount calculation for 20165.
[getmangos.git] / src / game / SpellEffects.cpp
blob0e437fd1a55d1299dbbd95041bb711bed72e9c2f
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectCharge2, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL, //160 SPELL_EFFECT_160 unused
221 &Spell::EffectNULL, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectNULL, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(uint32 /*i*/)
227 sLog.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(uint32 /*i*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(uint32 i)
237 if(!unitTarget || unitTarget->isAlive())
238 return;
240 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
241 return;
243 if(!unitTarget->IsInWorld())
244 return;
246 Player* pTarget = ((Player*)unitTarget);
248 if(pTarget->isRessurectRequested()) // already have one active request
249 return;
251 uint32 health = damage;
252 uint32 mana = m_spellInfo->EffectMiscValue[i];
253 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
254 SendResurrectRequest(pTarget);
257 void Spell::EffectInstaKill(uint32 /*i*/)
259 if( !unitTarget || !unitTarget->isAlive() )
260 return;
262 // Demonic Sacrifice
263 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
265 uint32 entry = unitTarget->GetEntry();
266 uint32 spellID;
267 switch(entry)
269 case 416: spellID=18789; break; //imp
270 case 417: spellID=18792; break; //fellhunter
271 case 1860: spellID=18790; break; //void
272 case 1863: spellID=18791; break; //succubus
273 case 17252: spellID=35701; break; //fellguard
274 default:
275 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
276 return;
279 m_caster->CastSpell(m_caster, spellID, true);
282 if(m_caster == unitTarget) // prevent interrupt message
283 finish();
285 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
288 void Spell::EffectEnvironmentalDMG(uint32 i)
290 uint32 absorb = 0;
291 uint32 resist = 0;
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage = m_spellInfo->CalculateSimpleValue(i);
298 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
300 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
301 if(m_caster->GetTypeId() == TYPEID_PLAYER)
302 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
305 void Spell::EffectSchoolDMG(uint32 effect_idx)
307 if( unitTarget && unitTarget->isAlive())
309 switch(m_spellInfo->SpellFamilyName)
311 case SPELLFAMILY_GENERIC:
313 switch(m_spellInfo->Id) // better way to check unknown
315 // Meteor like spells (divided damage to targets)
316 case 24340: case 26558: case 28884: // Meteor
317 case 36837: case 38903: case 41276: // Meteor
318 case 26789: // Shard of the Fallen Star
319 case 31436: // Malevolent Cleave
320 case 35181: // Dive Bomb
321 case 40810: case 43267: case 43268: // Saber Lash
322 case 42384: // Brutal Swipe
323 case 45150: // Meteor Slash
324 case 64422: case 64688: // Sonic Screech
326 uint32 count = 0;
327 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
328 if(ihit->effectMask & (1<<effect_idx))
329 ++count;
331 damage /= count; // divide to all targets
332 break;
334 // percent from health with min
335 case 25599: // Thundercrash
337 damage = unitTarget->GetHealth() / 2;
338 if(damage < 200)
339 damage = 200;
340 break;
342 // Intercept (warrior spell trigger)
343 case 20253:
344 case 61491:
346 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
347 break;
349 // Cataclysmic Bolt
350 case 38441:
352 damage = unitTarget->GetMaxHealth() / 2;
353 break;
355 // Tympanic Tantrum
356 case 62775:
358 damage = unitTarget->GetMaxHealth() / 10;
359 break;
361 // Hand of Rekoning (name not have typos ;) )
362 case 67485:
363 damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
364 break;
366 break;
368 case SPELLFAMILY_MAGE:
369 // remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
370 // NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
371 if ((m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_ARCANE) && !(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000)))
372 m_caster->RemoveAurasDueToSpell(36032); // Arcane Blast buff
373 break;
374 case SPELLFAMILY_WARRIOR:
376 // Bloodthirst
377 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
379 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
381 // Shield Slam
382 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
383 damage += int32(m_caster->GetShieldBlockValue());
384 // Victory Rush
385 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
387 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
388 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
390 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
391 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
392 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
393 // Heroic Throw ${$m1+$AP*.50}
394 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
395 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
396 // Shockwave ${$m3/100*$AP}
397 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
399 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
400 if (pct > 0)
401 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
402 break;
404 // Thunder Clap
405 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
407 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
409 break;
411 case SPELLFAMILY_WARLOCK:
413 // Incinerate Rank 1 & 2
414 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
416 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
417 // Check aura state for speed but aura state set not only for Immolate spell
418 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
420 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
421 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
423 // Immolate
424 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
425 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
427 damage += damage/4;
428 break;
433 // Shadowflame
434 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
436 // Apply DOT part
437 switch(m_spellInfo->Id)
439 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
440 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
441 default:
442 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
443 break;
446 // Conflagrate - consumes Immolate or Shadowflame
447 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
449 Aura const* aura = NULL; // found req. aura for damage calculation
451 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
452 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
454 // for caster applied auras only
455 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
456 (*i)->GetCasterGUID()!=m_caster->GetGUID())
457 continue;
459 // Immolate
460 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
462 aura = *i; // it selected always if exist
463 break;
466 // Shadowflame
467 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
468 aura = *i; // remember but wait possible Immolate as primary priority
471 // found Immolate or Shadowflame
472 if (aura)
474 // DoT not have applied spell bonuses in m_amount
475 int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
476 damage += damagetick * 4;
478 // Glyph of Conflagrate
479 if (!m_caster->HasAura(56235))
480 unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
481 break;
484 break;
486 case SPELLFAMILY_PRIEST:
488 // Shadow Word: Death - deals damage equal to damage done to caster
489 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
490 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
491 // Improved Mind Blast (Mind Blast in shadow form bonus)
492 else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000)))
494 Unit::AuraList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
495 for(Unit::AuraList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
497 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
498 ((*i)->GetSpellProto()->SpellIconID == 95))
500 int chance = (*i)->GetSpellProto()->CalculateSimpleValue(1);
501 if (roll_chance_i(chance))
502 // Mind Trauma
503 m_caster->CastSpell(unitTarget, 48301, true, 0);
504 break;
508 break;
510 case SPELLFAMILY_DRUID:
512 // Ferocious Bite
513 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
515 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
516 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
517 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
518 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
519 uint32 energy = m_caster->GetPower(POWER_ENERGY);
520 uint32 used_energy = energy > 30 ? 30 : energy;
521 damage += int32(used_energy * multiple);
522 m_caster->SetPower(POWER_ENERGY,energy-used_energy);
524 // Rake
525 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS)
527 // $AP*0.01 bonus
528 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
530 // Swipe
531 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
533 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
535 break;
537 case SPELLFAMILY_ROGUE:
539 // Envenom
540 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
542 // consume from stack dozes not more that have combo-points
543 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
545 Aura *poison = 0;
546 // Lookup for Deadly poison (only attacker applied)
547 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
548 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
549 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
550 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
551 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
553 poison = *itr;
554 break;
556 // count consumed deadly poison doses at target
557 if (poison)
559 uint32 spellId = poison->GetId();
560 uint32 doses = poison->GetStackAmount();
561 if (doses > combo)
562 doses = combo;
563 for (int i=0; i< doses; i++)
564 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
565 damage *= doses;
566 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
568 // Eviscerate and Envenom Bonus Damage (item set effect)
569 if(m_caster->GetDummyAura(37169))
570 damage += ((Player*)m_caster)->GetComboPoints()*40;
573 // Eviscerate
574 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
576 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
578 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
579 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
581 // Eviscerate and Envenom Bonus Damage (item set effect)
582 if(m_caster->GetDummyAura(37169))
583 damage += combo*40;
586 // Gouge
587 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
589 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
591 // Instant Poison
592 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
594 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
596 // Wound Poison
597 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
599 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
601 break;
603 case SPELLFAMILY_HUNTER:
605 //Gore
606 if (m_spellInfo->SpellIconID == 1578)
608 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
609 damage *= 2;
611 // Mongoose Bite
612 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
614 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
616 // Counterattack
617 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
619 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
621 // Arcane Shot
622 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
624 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
626 // Steady Shot
627 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
629 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
630 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
632 // Explosive Trap Effect
633 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
635 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
637 break;
639 case SPELLFAMILY_PALADIN:
641 // Judgement of Righteousness - receive benefit from Spell Damage and Attack power
642 if (m_spellInfo->Id == 20187)
644 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
645 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
646 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
647 damage += int32(ap * 0.2f) + int32(holy * 32 / 100);
649 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
650 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
652 uint32 debuf_id;
653 switch(m_spellInfo->Id)
655 case 53733: debuf_id = 53742; break;// Judgement of Corruption -> Blood Corruption
656 case 31804: debuf_id = 31803; break;// Judgement of Vengeance -> Holy Vengeance
657 default: return;
660 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
661 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
662 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
663 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
664 // Get stack of Holy Vengeance on the target added by caster
665 uint32 stacks = 0;
666 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
667 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
669 if( ((*itr)->GetId() == debuf_id) && (*itr)->GetCasterGUID()==m_caster->GetGUID())
671 stacks = (*itr)->GetStackAmount();
672 break;
675 // + 10% for each application of Holy Vengeance on the target
676 if(stacks)
677 damage += damage * stacks * 10 /100;
679 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
680 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
682 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
683 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
684 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
685 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
687 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
688 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
690 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
691 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
692 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
693 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
695 // Hammer of the Righteous
696 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
698 // Add main hand dps * effect[2] amount
699 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
700 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
701 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
703 // Shield of Righteousness
704 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
706 damage+=int32(m_caster->GetShieldBlockValue());
708 // Judgement
709 else if (m_spellInfo->Id == 54158)
711 // [1 + 0.25 * SPH + 0.16 * AP]
712 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
714 break;
718 if(damage >= 0)
719 m_damage += damage;
723 void Spell::EffectDummy(uint32 i)
725 if (!unitTarget && !gameObjTarget && !itemTarget)
726 return;
728 // selection by spell family
729 switch(m_spellInfo->SpellFamilyName)
731 case SPELLFAMILY_GENERIC:
733 switch(m_spellInfo->Id )
735 case 8063: // Deviate Fish
737 if (m_caster->GetTypeId() != TYPEID_PLAYER)
738 return;
740 uint32 spell_id = 0;
741 switch(urand(1,5))
743 case 1: spell_id = 8064; break; // Sleepy
744 case 2: spell_id = 8065; break; // Invigorate
745 case 3: spell_id = 8066; break; // Shrink
746 case 4: spell_id = 8067; break; // Party Time!
747 case 5: spell_id = 8068; break; // Healthy Spirit
749 m_caster->CastSpell(m_caster, spell_id, true, NULL);
750 return;
752 case 8213: // Savory Deviate Delight
754 if (m_caster->GetTypeId() != TYPEID_PLAYER)
755 return;
757 uint32 spell_id = 0;
758 switch(urand(1,2))
760 // Flip Out - ninja
761 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
762 // Yaaarrrr - pirate
763 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
765 m_caster->CastSpell(m_caster,spell_id,true,NULL);
766 return;
768 case 8593: // Symbol of life (restore creature to life)
769 case 31225: // Shimmering Vessel (restore creature to life)
771 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
772 return;
773 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
774 return;
776 case 13120: // net-o-matic
778 if (!unitTarget)
779 return;
781 uint32 spell_id = 0;
783 uint32 roll = urand(0, 99);
785 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
786 spell_id = 16566;
787 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
788 spell_id = 13119;
789 else // normal root
790 spell_id = 13099;
792 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
793 return;
795 case 13567: // Dummy Trigger
797 // can be used for different aura triggering, so select by aura
798 if (!m_triggeredByAuraSpell || !unitTarget)
799 return;
801 switch(m_triggeredByAuraSpell->Id)
803 case 26467: // Persistent Shield
804 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
805 break;
806 default:
807 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
808 break;
810 return;
812 case 15998: // Capture Worg Pup
813 case 29435: // Capture Female Kaliri Hatchling
815 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
816 return;
818 Creature* creatureTarget = (Creature*)unitTarget;
820 creatureTarget->ForcedDespawn();
821 return;
823 case 16589: // Noggenfogger Elixir
825 if (m_caster->GetTypeId() != TYPEID_PLAYER)
826 return;
828 uint32 spell_id = 0;
829 switch(urand(1, 3))
831 case 1: spell_id = 16595; break;
832 case 2: spell_id = 16593; break;
833 default:spell_id = 16591; break;
836 m_caster->CastSpell(m_caster, spell_id, true, NULL);
837 return;
839 case 17251: // Spirit Healer Res
841 if (!unitTarget || !m_originalCaster)
842 return;
844 if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
846 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
847 data << uint64(unitTarget->GetGUID());
848 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
850 return;
852 case 17271: // Test Fetid Skull
854 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
855 return;
857 uint32 spell_id = roll_chance_i(50)
858 ? 17269 // Create Resonating Skull
859 : 17270; // Create Bone Dust
861 m_caster->CastSpell(m_caster, spell_id, true, NULL);
862 return;
864 case 20577: // Cannibalize
865 if (unitTarget)
866 m_caster->CastSpell(m_caster, 20578, false, NULL);
867 return;
868 case 23019: // Crystal Prison Dummy DND
870 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
871 return;
873 Creature* creatureTarget = (Creature*)unitTarget;
874 if (creatureTarget->isPet())
875 return;
877 GameObject* pGameObj = new GameObject;
879 Map *map = creatureTarget->GetMap();
881 // create before death for get proper coordinates
882 if (!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
883 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
884 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
886 delete pGameObj;
887 return;
890 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
891 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
892 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
893 pGameObj->SetSpellId(m_spellInfo->Id);
895 creatureTarget->ForcedDespawn();
897 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
898 map->Add(pGameObj);
900 return;
902 case 23074: // Arcanite Dragonling
903 if (!m_CastItem)
904 return;
905 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
906 return;
907 case 23075: // Mithril Mechanical Dragonling
908 if (!m_CastItem)
909 return;
910 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
911 return;
912 case 23076: // Mechanical Dragonling
913 if (!m_CastItem)
914 return;
915 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
916 return;
917 case 23133: // Gnomish Battle Chicken
918 if (!m_CastItem)
919 return;
920 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
921 return;
922 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
924 int32 r = irand(0, 119);
925 if (r < 20) // Transporter Malfunction - 1/6 polymorph
926 m_caster->CastSpell(m_caster, 23444, true);
927 else if (r < 100) // Evil Twin - 4/6 evil twin
928 m_caster->CastSpell(m_caster, 23445, true);
929 else // Transporter Malfunction - 1/6 miss the target
930 m_caster->CastSpell(m_caster, 36902, true);
931 return;
933 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
934 if (roll_chance_i(50)) // Gadgetzan Transporter - success
935 m_caster->CastSpell(m_caster, 23441, true);
936 else // Gadgetzan Transporter Failure - failure
937 m_caster->CastSpell(m_caster, 23446, true);
938 return;
939 case 23645: // Hourglass Sand
940 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
941 return;
942 case 23725: // Gift of Life (warrior bwl trinket)
943 m_caster->CastSpell(m_caster, 23782, true);
944 m_caster->CastSpell(m_caster, 23783, true);
945 return;
946 case 25860: // Reindeer Transformation
948 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
949 return;
951 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
952 float speed = m_caster->GetSpeedRate(MOVE_RUN);
954 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
956 //5 different spells used depending on mounted speed and if mount can fly or not
957 if (flyspeed >= 4.1f)
958 // Flying Reindeer
959 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
960 else if (flyspeed >= 3.8f)
961 // Flying Reindeer
962 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
963 else if (flyspeed >= 1.6f)
964 // Flying Reindeer
965 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
966 else if (speed >= 2.0f)
967 // Reindeer
968 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
969 else
970 // Reindeer
971 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
973 return;
975 case 26074: // Holiday Cheer
976 // implemented at client side
977 return;
978 case 28006: // Arcane Cloaking
980 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
981 // Naxxramas Entry Flag Effect DND
982 m_caster->CastSpell(unitTarget, 29294, true);
983 return;
985 case 29200: // Purify Helboar Meat
987 if (m_caster->GetTypeId() != TYPEID_PLAYER)
988 return;
990 uint32 spell_id = roll_chance_i(50)
991 ? 29277 // Summon Purified Helboar Meat
992 : 29278; // Summon Toxic Helboar Meat
994 m_caster->CastSpell(m_caster,spell_id,true,NULL);
995 return;
997 case 29858: // Soulshatter
998 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
999 m_caster->CastSpell(unitTarget,32835,true);
1000 return;
1001 case 30458: // Nigh Invulnerability
1002 if (!m_CastItem)
1003 return;
1004 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1005 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1006 else // Complete Vulnerability - backfire in 14% casts
1007 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1008 return;
1009 case 30507: // Poultryizer
1010 if(!m_CastItem)
1011 return;
1012 if (roll_chance_i(80)) // Poultryized! - success
1013 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1014 else // Poultryized! - backfire 20%
1015 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1016 return;
1017 case 33060: // Make a Wish
1019 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1020 return;
1022 uint32 spell_id = 0;
1024 switch(urand(1,5))
1026 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1027 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1028 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1029 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1030 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1033 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1034 return;
1036 case 34665: //Administer Antidote
1038 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1039 return;
1040 // Spell has scriptable target but for sure.
1041 if (unitTarget->GetTypeId() != TYPEID_UNIT)
1042 return;
1044 uint32 health = unitTarget->GetHealth();
1045 float x, y, z, o;
1047 unitTarget->GetPosition(x, y, z);
1048 o = unitTarget->GetOrientation();
1049 ((Creature*)unitTarget)->ForcedDespawn();
1051 if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000))
1053 summon->SetHealth(health);
1054 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon);
1056 if (summon->AI())
1057 summon->AI()->AttackStart(m_caster);
1059 return;
1061 case 35745: // Socrethar's Stone
1063 uint32 spell_id;
1064 switch(m_caster->GetAreaId())
1066 case 3900: spell_id = 35743; break; // Socrethar Portal
1067 case 3742: spell_id = 35744; break; // Socrethar Portal
1068 default: return;
1071 m_caster->CastSpell(m_caster, spell_id, true);
1072 return;
1074 case 37674: // Chaos Blast
1076 if (!unitTarget)
1077 return;
1079 int32 basepoints0 = 100;
1080 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1081 return;
1083 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1085 // selecting one from Bloodstained Fortune item
1086 uint32 newitemid;
1087 switch(urand(1, 20))
1089 case 1: newitemid = 32688; break;
1090 case 2: newitemid = 32689; break;
1091 case 3: newitemid = 32690; break;
1092 case 4: newitemid = 32691; break;
1093 case 5: newitemid = 32692; break;
1094 case 6: newitemid = 32693; break;
1095 case 7: newitemid = 32700; break;
1096 case 8: newitemid = 32701; break;
1097 case 9: newitemid = 32702; break;
1098 case 10: newitemid = 32703; break;
1099 case 11: newitemid = 32704; break;
1100 case 12: newitemid = 32705; break;
1101 case 13: newitemid = 32706; break;
1102 case 14: newitemid = 32707; break;
1103 case 15: newitemid = 32708; break;
1104 case 16: newitemid = 32709; break;
1105 case 17: newitemid = 32710; break;
1106 case 18: newitemid = 32711; break;
1107 case 19: newitemid = 32712; break;
1108 case 20: newitemid = 32713; break;
1109 default:
1110 return;
1113 DoCreateItem(i, newitemid);
1114 return;
1116 // Demon Broiled Surprise
1117 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1118 case 43723:
1120 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1121 return;
1123 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1124 return;
1127 case 44875: // Complete Raptor Capture
1129 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1130 return;
1132 Creature* creatureTarget = (Creature*)unitTarget;
1134 creatureTarget->ForcedDespawn();
1136 //cast spell Raptor Capture Credit
1137 m_caster->CastSpell(m_caster, 42337, true, NULL);
1138 return;
1140 case 44997: // Converting Sentry
1142 //Converted Sentry Credit
1143 m_caster->CastSpell(m_caster, 45009, true);
1144 return;
1146 case 45030: // Impale Emissary
1148 // Emissary of Hate Credit
1149 m_caster->CastSpell(m_caster, 45088, true);
1150 return;
1152 case 49357: // Brewfest Mount Transformation
1153 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1154 return;
1156 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1157 return;
1159 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1161 // Ram for Alliance, Kodo for Horde
1162 if (((Player *)m_caster)->GetTeam() == ALLIANCE)
1164 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1165 // 100% Ram
1166 m_caster->CastSpell(m_caster, 43900, true);
1167 else
1168 // 60% Ram
1169 m_caster->CastSpell(m_caster, 43899, true);
1171 else
1173 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1174 // 100% Kodo
1175 m_caster->CastSpell(m_caster, 49379, true);
1176 else
1177 // 60% Kodo
1178 m_caster->CastSpell(m_caster, 49378, true);
1180 return;
1181 case 50243: // Teach Language
1183 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1184 return;
1186 // spell has a 1/3 chance to trigger one of the below
1187 if (roll_chance_i(66))
1188 return;
1189 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1191 // 1000001 - gnomish binary
1192 m_caster->CastSpell(m_caster, 50242, true);
1194 else
1196 // 01001000 - goblin binary
1197 m_caster->CastSpell(m_caster, 50246, true);
1200 return;
1202 case 46167: // Planning for the Future: Create Snowfall Glade Pup Cover
1203 case 50926: // Gluttonous Lurkers: Create Zul'Drak Rat Cover
1204 case 51026: // Create Drakkari Medallion Cover
1205 case 51592: // Pickup Primordial Hatchling
1206 case 51961: // Captured Chicken Cover
1208 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
1209 return;
1211 uint32 spellId = 0;
1213 switch(m_spellInfo->Id)
1215 case 46167: spellId = 46773; break;
1216 case 50926: spellId = 50927; break;
1217 case 51026: spellId = 50737; break;
1218 case 51592: spellId = 51593; break;
1219 case 51961: spellId = 51037; break;
1222 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(spellId))
1224 unitTarget->CastSpell(m_caster, spellId, true);
1226 Creature* creatureTarget = (Creature*)unitTarget;
1228 if (const SpellCastTimesEntry *pCastTime = sSpellCastTimesStore.LookupEntry(pSpell->CastingTimeIndex))
1229 creatureTarget->ForcedDespawn(pCastTime->CastTime + 1);
1231 return;
1233 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1235 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1236 return;
1238 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1239 bg->EventPlayerDroppedFlag((Player*)m_caster);
1241 m_caster->CastSpell(m_caster, 30452, true, NULL);
1242 return;
1244 case 52308: // Take Sputum Sample
1246 switch(i)
1248 case 0:
1250 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1251 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1253 if (m_caster->HasAura(reqAuraID,0))
1254 m_caster->CastSpell(m_caster, spellID, true, NULL);
1255 return;
1257 case 1:
1258 return; // additional data for dummy[0]
1260 return;
1262 case 52759: // Ancestral Awakening
1263 if (!unitTarget)
1264 return;
1265 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1266 return;
1267 case 52845: // Brewfest Mount Transformation (Faction Swap)
1268 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1269 return;
1271 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1272 return;
1274 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1276 // Ram for Horde, Kodo for Alliance
1277 if (((Player *)m_caster)->GetTeam() == HORDE)
1279 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1280 // Swift Brewfest Ram, 100% Ram
1281 m_caster->CastSpell(m_caster, 43900, true);
1282 else
1283 // Brewfest Ram, 60% Ram
1284 m_caster->CastSpell(m_caster, 43899, true);
1286 else
1288 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1289 // Great Brewfest Kodo, 100% Kodo
1290 m_caster->CastSpell(m_caster, 49379, true);
1291 else
1292 // Brewfest Riding Kodo, 60% Kodo
1293 m_caster->CastSpell(m_caster, 49378, true);
1295 return;
1296 case 53341: // Rune of Cinderglacier
1297 case 53343: // Rune of Razorice
1299 // Runeforging Credit
1300 m_caster->CastSpell(m_caster, 54586, true);
1301 return;
1303 case 55004: // Nitro Boosts
1304 if (!m_CastItem)
1305 return;
1306 if (roll_chance_i(95)) // Nitro Boosts - success
1307 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1308 else // Knocked Up - backfire 5%
1309 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1310 return;
1311 case 58418: // Portal to Orgrimmar
1312 case 58420: // Portal to Stormwind
1313 return; // implemented in EffectScript[0]
1314 case 59640: // Underbelly Elixir
1316 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1317 return;
1319 uint32 spell_id = 0;
1320 switch(urand(1,3))
1322 case 1: spell_id = 59645; break;
1323 case 2: spell_id = 59831; break;
1324 case 3: spell_id = 59843; break;
1326 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1327 return;
1329 case 60932: // Disengage (one from creature versions)
1330 if (!unitTarget)
1331 return;
1332 m_caster->CastSpell(unitTarget,60934,true,NULL);
1333 return;
1334 case 67019: // Flask of the North
1336 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1337 return;
1339 uint32 spell_id = 0;
1340 switch(m_caster->getClass())
1342 case CLASS_WARRIOR:
1343 case CLASS_DEATH_KNIGHT:
1344 spell_id = 67018; // STR for Warriors, Death Knights
1345 break;
1346 case CLASS_ROGUE:
1347 case CLASS_HUNTER:
1348 spell_id = 67017; // AP for Rogues, Hunters
1349 break;
1350 case CLASS_PRIEST:
1351 case CLASS_MAGE:
1352 case CLASS_WARLOCK:
1353 spell_id = 67016; // SPD for Priests, Mages, Warlocks
1354 break;
1355 case CLASS_SHAMAN:
1356 // random (SPD, AP)
1357 spell_id = roll_chance_i(50) ? 67016 : 67017;
1358 break;
1359 case CLASS_PALADIN:
1360 case CLASS_DRUID:
1361 default:
1362 // random (SPD, STR)
1363 spell_id = roll_chance_i(50) ? 67016 : 67018;
1364 break;
1366 m_caster->CastSpell(m_caster, spell_id, true);
1367 return;
1370 break;
1372 case SPELLFAMILY_MAGE:
1373 switch(m_spellInfo->Id )
1375 case 11958: // Cold Snap
1377 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1378 return;
1380 // immediately finishes the cooldown on Frost spells
1381 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1382 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1384 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1386 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1387 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1388 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1390 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1392 else
1393 ++itr;
1395 return;
1397 case 32826: // Polymorph Cast Visual
1399 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1401 //Polymorph Cast Visual Rank 1
1402 const uint32 spell_list[6] = {
1403 32813, // Squirrel Form
1404 32816, // Giraffe Form
1405 32817, // Serpent Form
1406 32818, // Dragonhawk Form
1407 32819, // Worgen Form
1408 32820 // Sheep Form
1410 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1412 return;
1415 break;
1416 case SPELLFAMILY_WARRIOR:
1417 // Charge
1418 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1420 int32 chargeBasePoints0 = damage;
1421 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1422 return;
1424 // Execute
1425 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1427 if(!unitTarget)
1428 return;
1430 uint32 rage = m_caster->GetPower(POWER_RAGE);
1432 // up to max 30 rage cost
1433 if(rage > 300)
1434 rage = 300;
1436 // Glyph of Execution bonus
1437 uint32 rage_modified = rage;
1439 if (Aura *aura = m_caster->GetDummyAura(58367))
1440 rage_modified += aura->GetModifier()->m_amount*10;
1442 int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[i] +
1443 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1445 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1447 // Sudden Death
1448 if(m_caster->HasAura(52437))
1450 Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
1451 for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1453 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1454 if ((*itr)->GetSpellProto()->SpellIconID == 1989)
1456 // saved rage top stored in next affect
1457 uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(1)*10;
1458 if(lastrage < rage)
1459 rage -= lastrage;
1460 break;
1465 m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
1466 return;
1468 // Slam
1469 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1471 if(!unitTarget)
1472 return;
1473 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1474 m_damage+=damage;
1475 return;
1477 // Concussion Blow
1478 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1480 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1481 return;
1484 switch(m_spellInfo->Id)
1486 // Warrior's Wrath
1487 case 21977:
1489 if (!unitTarget)
1490 return;
1491 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1492 return;
1494 // Last Stand
1495 case 12975:
1497 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1498 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1499 return;
1501 // Bloodthirst
1502 case 23881:
1504 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1505 return;
1508 break;
1509 case SPELLFAMILY_WARLOCK:
1510 // Life Tap
1511 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1513 // In 303 exist spirit depend
1514 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1515 switch (m_spellInfo->Id)
1517 case 1454: damage+=spirit; break;
1518 case 1455: damage+=spirit*15/10; break;
1519 case 1456: damage+=spirit*2; break;
1520 case 11687: damage+=spirit*25/10; break;
1521 case 11688:
1522 case 11689:
1523 case 27222:
1524 case 57946: damage+=spirit*3; break;
1525 default:
1526 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1527 return;
1529 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1530 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1531 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1533 // Shouldn't Appear in Combat Log
1534 unitTarget->ModifyHealth(-damage);
1536 int32 mana = damage;
1537 // Improved Life Tap mod
1538 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1539 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1541 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1542 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1544 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1546 // Mana Feed
1547 int32 manaFeedVal = 0;
1548 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1549 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1551 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1552 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1554 if (manaFeedVal > 0)
1556 manaFeedVal = manaFeedVal * mana / 100;
1557 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1560 else
1561 SendCastResult(SPELL_FAILED_FIZZLE);
1562 return;
1564 break;
1565 case SPELLFAMILY_PRIEST:
1566 // Penance
1567 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1569 if (!unitTarget)
1570 return;
1572 int hurt = 0;
1573 int heal = 0;
1574 switch(m_spellInfo->Id)
1576 case 47540: hurt = 47758; heal = 47757; break;
1577 case 53005: hurt = 53001; heal = 52986; break;
1578 case 53006: hurt = 53002; heal = 52987; break;
1579 case 53007: hurt = 53003; heal = 52988; break;
1580 default:
1581 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1582 return;
1584 if (m_caster->IsFriendlyTo(unitTarget))
1585 m_caster->CastSpell(unitTarget, heal, true, 0);
1586 else
1587 m_caster->CastSpell(unitTarget, hurt, true, 0);
1588 return;
1590 break;
1591 case SPELLFAMILY_DRUID:
1592 // Starfall
1593 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100)
1595 //Shapeshifting into an animal form or mounting cancels the effect.
1596 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1598 if(m_triggeredByAuraSpell)
1599 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1600 return;
1603 //Any effect which causes you to lose control of your character will supress the starfall effect.
1604 if (m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1605 return;
1607 switch(m_spellInfo->Id)
1609 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1610 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1611 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1612 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1613 default:
1614 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1615 return;
1618 break;
1619 case SPELLFAMILY_ROGUE:
1620 switch(m_spellInfo->Id )
1622 case 5938: // Shiv
1624 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1625 return;
1627 Player *pCaster = ((Player*)m_caster);
1629 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1630 if (!item)
1631 return;
1633 // all poison enchantments is temporary
1634 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1635 if (!enchant_id)
1636 return;
1638 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1639 if (!pEnchant)
1640 return;
1642 for (int s=0;s<3;s++)
1644 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1645 continue;
1647 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1648 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1649 continue;
1651 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1654 m_caster->CastSpell(unitTarget, 5940, true);
1655 return;
1657 case 14185: // Preparation
1659 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1660 return;
1662 //immediately finishes the cooldown on certain Rogue abilities
1663 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1664 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1666 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1668 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1669 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1670 else
1671 ++itr;
1673 return;
1675 case 31231: // Cheat Death
1677 m_caster->CastSpell(m_caster, 45182, true);
1678 return;
1681 break;
1682 case SPELLFAMILY_HUNTER:
1683 // Steady Shot
1684 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1686 if (!unitTarget || !unitTarget->isAlive())
1687 return;
1689 bool found = false;
1691 // check dazed affect
1692 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1693 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1695 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1697 found = true;
1698 break;
1702 if (found)
1703 m_damage+= damage;
1704 return;
1707 // Disengage
1708 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
1710 Unit* target = unitTarget;
1711 uint32 spellid;
1712 switch(m_spellInfo->Id)
1714 case 57635: spellid = 57636; break; // one from creature cases
1715 case 61507: spellid = 61508; break; // one from creature cases
1716 default:
1717 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
1718 return;
1720 if (!target || !target->isAlive())
1721 return;
1722 m_caster->CastSpell(target,spellid,true,NULL);
1725 switch(m_spellInfo->Id)
1727 case 23989: // Readiness talent
1729 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1730 return;
1732 //immediately finishes the cooldown for hunter abilities
1733 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
1734 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1736 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1738 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1739 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1740 else
1741 ++itr;
1743 return;
1745 case 37506: // Scatter Shot
1747 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1748 return;
1750 // break Auto Shot and autohit
1751 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1752 m_caster->AttackStop();
1753 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1754 return;
1756 // Last Stand
1757 case 53478:
1759 if (!unitTarget)
1760 return;
1761 int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
1762 unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1763 return;
1765 // Master's Call
1766 case 53271:
1768 Pet* pet = m_caster->GetPet();
1769 if (!pet || !unitTarget)
1770 return;
1772 pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(i), true);
1773 return;
1776 break;
1777 case SPELLFAMILY_PALADIN:
1778 switch(m_spellInfo->SpellIconID)
1780 case 156: // Holy Shock
1782 if (!unitTarget)
1783 return;
1785 int hurt = 0;
1786 int heal = 0;
1788 switch(m_spellInfo->Id)
1790 case 20473: hurt = 25912; heal = 25914; break;
1791 case 20929: hurt = 25911; heal = 25913; break;
1792 case 20930: hurt = 25902; heal = 25903; break;
1793 case 27174: hurt = 27176; heal = 27175; break;
1794 case 33072: hurt = 33073; heal = 33074; break;
1795 case 48824: hurt = 48822; heal = 48820; break;
1796 case 48825: hurt = 48823; heal = 48821; break;
1797 default:
1798 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1799 return;
1802 if (m_caster->IsFriendlyTo(unitTarget))
1803 m_caster->CastSpell(unitTarget, heal, true, 0);
1804 else
1805 m_caster->CastSpell(unitTarget, hurt, true, 0);
1807 return;
1809 case 561: // Judgement of command
1811 if (!unitTarget)
1812 return;
1814 uint32 spell_id = m_currentBasePoints[i]+1;
1815 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1816 if (!spell_proto)
1817 return;
1819 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1820 return;
1824 switch(m_spellInfo->Id)
1826 case 31789: // Righteous Defense (step 1)
1828 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1830 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1831 return;
1834 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1835 Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
1836 if (friendTarget)
1838 Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
1839 if (!player || !player->IsInSameRaidWith((Player*)m_caster))
1840 friendTarget = NULL;
1843 // non-standard cast requirement check
1844 if (!friendTarget || friendTarget->getAttackers().empty())
1846 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
1847 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1848 return;
1851 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1852 // Clear targets for eff 1
1853 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1854 ihit->effectMask &= ~(1<<1);
1856 // not empty (checked), copy
1857 Unit::AttackerSet attackers = friendTarget->getAttackers();
1859 // selected from list 3
1860 for(int i = 0; i < std::min(size_t(3),attackers.size()); ++i)
1862 Unit::AttackerSet::iterator aItr = attackers.begin();
1863 std::advance(aItr, rand() % attackers.size());
1864 AddUnitTarget((*aItr), 1);
1865 attackers.erase(aItr);
1868 // now let next effect cast spell at each target.
1869 return;
1871 case 37877: // Blessing of Faith
1873 if (!unitTarget)
1874 return;
1876 uint32 spell_id = 0;
1877 switch(unitTarget->getClass())
1879 case CLASS_DRUID: spell_id = 37878; break;
1880 case CLASS_PALADIN: spell_id = 37879; break;
1881 case CLASS_PRIEST: spell_id = 37880; break;
1882 case CLASS_SHAMAN: spell_id = 37881; break;
1883 default: return; // ignore for not healing classes
1886 m_caster->CastSpell(m_caster, spell_id, true);
1887 return;
1890 break;
1891 case SPELLFAMILY_SHAMAN:
1892 // Cleansing Totem
1893 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
1895 if (unitTarget)
1896 m_caster->CastSpell(unitTarget, 52025, true);
1897 return;
1899 // Healing Stream Totem
1900 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
1902 if (unitTarget)
1903 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1904 return;
1906 // Mana Spring Totem
1907 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
1909 if (!unitTarget || unitTarget->getPowerType()!=POWER_MANA)
1910 return;
1911 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1912 return;
1914 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
1916 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1917 return;
1918 // Glyph of Mana Tide
1919 if (Unit *owner = m_caster->GetOwner())
1920 if (Aura *dummy = owner->GetDummyAura(55441))
1921 damage+=dummy->GetModifier()->m_amount;
1922 // Regenerate 6% of Total Mana Every 3 secs
1923 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1924 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1925 return;
1927 // Lava Lash
1928 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1930 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1931 return;
1932 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1933 if (item)
1935 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1936 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1937 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1939 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1940 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
1941 (*itr)->GetCastItemGUID() == item->GetGUID())
1943 m_damage += m_damage * damage / 100;
1944 return;
1948 return;
1950 break;
1951 case SPELLFAMILY_DEATHKNIGHT:
1952 // Death Coil
1953 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
1955 if (m_caster->IsFriendlyTo(unitTarget))
1957 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1958 return;
1960 int32 bp = damage * 1.5f;
1961 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
1963 else
1965 int32 bp = damage;
1966 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
1968 return;
1970 // Hungering Cold
1971 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
1973 m_caster->CastSpell(m_caster, 51209, true);
1974 return;
1976 // Death Strike
1977 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
1979 uint32 count = 0;
1980 Unit::AuraMap const& auras = unitTarget->GetAuras();
1981 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
1983 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
1984 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
1985 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
1987 ++count;
1988 // max. 15%
1989 if (count == 3)
1990 break;
1994 int32 bp = count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100;
1995 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
1996 return;
1998 break;
2001 // pet auras
2002 if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id, i))
2004 m_caster->AddPetAura(petSpell);
2005 return;
2008 // Script based implementation. Must be used only for not good for implementation in core spell effects
2009 // So called only for not proccessed cases
2010 if (gameObjTarget)
2011 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
2012 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
2013 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
2014 else if (itemTarget)
2015 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
2018 void Spell::EffectTriggerSpellWithValue(uint32 i)
2020 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2022 // normal case
2023 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2025 if(!spellInfo)
2027 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2028 return;
2031 int32 bp = damage;
2032 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
2035 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
2037 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2038 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2040 if(!spellInfo)
2042 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2043 return;
2046 finish();
2048 m_caster->CastSpell(unitTarget,spellInfo,false);
2051 void Spell::EffectForceCast(uint32 i)
2053 if( !unitTarget )
2054 return;
2056 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
2058 // normal case
2059 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2061 if(!spellInfo)
2063 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2064 return;
2067 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2070 void Spell::EffectTriggerSpell(uint32 effIndex)
2072 // only unit case known
2073 if (!unitTarget)
2075 if(gameObjTarget || itemTarget)
2076 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
2077 return;
2080 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2082 // special cases
2083 switch(triggered_spell_id)
2085 // Vanish (not exist)
2086 case 18461:
2088 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2089 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2090 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2092 // if this spell is given to NPC it must handle rest by it's own AI
2093 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2094 return;
2096 // get highest rank of the Stealth spell
2097 uint32 spellId = 0;
2098 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2099 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2101 // only highest rank is shown in spell book, so simply check if shown in spell book
2102 if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
2103 continue;
2105 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2106 if (!spellInfo)
2107 continue;
2109 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2111 spellId = spellInfo->Id;
2112 break;
2116 // no Stealth spell found
2117 if (!spellId)
2118 return;
2120 // reset cooldown on it if needed
2121 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2122 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2124 m_caster->CastSpell(unitTarget, spellId, true);
2125 return;
2127 // just skip
2128 case 23770: // Sayge's Dark Fortune of *
2129 // not exist, common cooldown can be implemented in scripts if need.
2130 return;
2131 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2132 case 29284:
2134 // Brittle Armor
2135 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2136 if (!spell)
2137 return;
2139 for (int j=0; j < spell->StackAmount; ++j)
2140 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2141 return;
2143 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2144 case 29286:
2146 // Mercurial Shield
2147 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2148 if (!spell)
2149 return;
2151 for (int j=0; j < spell->StackAmount; ++j)
2152 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2153 return;
2155 // Righteous Defense
2156 case 31980:
2158 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2159 return;
2161 // Cloak of Shadows
2162 case 35729:
2164 Unit::AuraMap& Auras = unitTarget->GetAuras();
2165 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2167 // remove all harmful spells on you...
2168 if( // ignore positive and passive auras
2169 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2170 // ignore physical auras
2171 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2173 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2174 iter = Auras.begin();
2177 return;
2179 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2180 case 41967:
2182 if (Unit *pet = unitTarget->GetPet())
2183 pet->CastSpell(pet, 28305, true);
2184 return;
2188 // normal case
2189 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2190 if (!spellInfo)
2192 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2193 return;
2196 // select formal caster for triggered spell
2197 Unit* caster = m_caster;
2199 // some triggered spells require specific equipment
2200 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2202 // main hand weapon required
2203 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2205 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
2207 // skip spell if no weapon in slot or broken
2208 if (!item)
2209 return;
2211 // skip spell if weapon not fit to triggered spell
2212 if (!item->IsFitToSpellRequirements(spellInfo))
2213 return;
2216 // offhand hand weapon required
2217 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2219 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
2221 // skip spell if no weapon in slot or broken
2222 if (!item)
2223 return;
2225 // skip spell if weapon not fit to triggered spell
2226 if (!item->IsFitToSpellRequirements(spellInfo))
2227 return;
2230 else
2232 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2233 // so this just for speedup places in else
2234 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2237 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2240 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2242 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2244 // normal case
2245 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2247 if(!spellInfo)
2249 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2250 m_spellInfo->Id,effect_idx,triggered_spell_id);
2251 return;
2254 if (m_CastItem)
2255 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2257 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2260 void Spell::EffectJump(uint32 i)
2262 if(m_caster->isInFlight())
2263 return;
2265 // Init dest coordinates
2266 float x,y,z,o;
2267 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2269 x = m_targets.m_destX;
2270 y = m_targets.m_destY;
2271 z = m_targets.m_destZ;
2273 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2275 // explicit cast data from client or server-side cast
2276 // some spell at client send caster
2277 Unit* pTarget = NULL;
2278 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2279 pTarget = m_targets.getUnitTarget();
2280 else if(unitTarget->getVictim())
2281 pTarget = m_caster->getVictim();
2282 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2283 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2285 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2287 else
2288 o = m_caster->GetOrientation();
2290 else if(unitTarget)
2292 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2293 o = m_caster->GetOrientation();
2295 else if(gameObjTarget)
2297 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2298 o = m_caster->GetOrientation();
2300 else
2302 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2303 return;
2306 m_caster->NearTeleportTo(x, y, z, o, true);
2309 void Spell::EffectTeleportUnits(uint32 i)
2311 if(!unitTarget || unitTarget->isInFlight())
2312 return;
2314 switch (m_spellInfo->EffectImplicitTargetB[i])
2316 case TARGET_INNKEEPER_COORDINATES:
2318 // Only players can teleport to innkeeper
2319 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2320 return;
2322 ((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
2323 return;
2325 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2326 case TARGET_TABLE_X_Y_Z_COORDINATES:
2328 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
2329 if(!st)
2331 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2332 return;
2335 if(st->target_mapId==unitTarget->GetMapId())
2336 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2337 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2338 ((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);
2339 break;
2341 case TARGET_BEHIND_VICTIM:
2343 Unit *pTarget = NULL;
2345 // explicit cast data from client or server-side cast
2346 // some spell at client send caster
2347 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2348 pTarget = m_targets.getUnitTarget();
2349 else if(unitTarget->getVictim())
2350 pTarget = unitTarget->getVictim();
2351 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2352 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2354 // Init dest coordinates
2355 float x = m_targets.m_destX;
2356 float y = m_targets.m_destY;
2357 float z = m_targets.m_destZ;
2358 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2359 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2360 return;
2362 default:
2364 // If not exist data for dest location - return
2365 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2367 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2368 return;
2370 // Init dest coordinates
2371 float x = m_targets.m_destX;
2372 float y = m_targets.m_destY;
2373 float z = m_targets.m_destZ;
2374 float orientation = unitTarget->GetOrientation();
2375 // Teleport
2376 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2377 return;
2381 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2382 switch ( m_spellInfo->Id )
2384 // Dimensional Ripper - Everlook
2385 case 23442:
2387 int32 r = irand(0, 119);
2388 if ( r >= 70 ) // 7/12 success
2390 if ( r < 100 ) // 4/12 evil twin
2391 m_caster->CastSpell(m_caster, 23445, true);
2392 else // 1/12 fire
2393 m_caster->CastSpell(m_caster, 23449, true);
2395 return;
2397 // Ultrasafe Transporter: Toshley's Station
2398 case 36941:
2400 if ( roll_chance_i(50) ) // 50% success
2402 int32 rand_eff = urand(1, 7);
2403 switch ( rand_eff )
2405 case 1:
2406 // soul split - evil
2407 m_caster->CastSpell(m_caster, 36900, true);
2408 break;
2409 case 2:
2410 // soul split - good
2411 m_caster->CastSpell(m_caster, 36901, true);
2412 break;
2413 case 3:
2414 // Increase the size
2415 m_caster->CastSpell(m_caster, 36895, true);
2416 break;
2417 case 4:
2418 // Decrease the size
2419 m_caster->CastSpell(m_caster, 36893, true);
2420 break;
2421 case 5:
2422 // Transform
2424 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2425 m_caster->CastSpell(m_caster, 36897, true);
2426 else
2427 m_caster->CastSpell(m_caster, 36899, true);
2428 break;
2430 case 6:
2431 // chicken
2432 m_caster->CastSpell(m_caster, 36940, true);
2433 break;
2434 case 7:
2435 // evil twin
2436 m_caster->CastSpell(m_caster, 23445, true);
2437 break;
2440 return;
2442 // Dimensional Ripper - Area 52
2443 case 36890:
2445 if ( roll_chance_i(50) ) // 50% success
2447 int32 rand_eff = urand(1, 4);
2448 switch ( rand_eff )
2450 case 1:
2451 // soul split - evil
2452 m_caster->CastSpell(m_caster, 36900, true);
2453 break;
2454 case 2:
2455 // soul split - good
2456 m_caster->CastSpell(m_caster, 36901, true);
2457 break;
2458 case 3:
2459 // Increase the size
2460 m_caster->CastSpell(m_caster, 36895, true);
2461 break;
2462 case 4:
2463 // Transform
2465 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2466 m_caster->CastSpell(m_caster, 36897, true);
2467 else
2468 m_caster->CastSpell(m_caster, 36899, true);
2469 break;
2473 return;
2478 void Spell::EffectApplyAura(uint32 i)
2480 if(!unitTarget)
2481 return;
2483 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2484 if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) &&
2485 (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2486 return;
2488 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2489 if(!caster)
2490 return;
2492 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2494 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2496 // Now Reduce spell duration using data received at spell hit
2497 int32 duration = Aur->GetAuraMaxDuration();
2498 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2499 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2500 Aur->setDiminishGroup(m_diminishGroup);
2502 // if Aura removed and deleted, do not continue.
2503 if(duration== 0 && !(Aur->IsPermanent()))
2505 delete Aur;
2506 return;
2509 if(duration != Aur->GetAuraMaxDuration())
2511 Aur->SetAuraMaxDuration(duration);
2512 Aur->SetAuraDuration(duration);
2515 unitTarget->AddAura(Aur);
2518 void Spell::EffectUnlearnSpecialization( uint32 i )
2520 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2521 return;
2523 Player *_player = (Player*)unitTarget;
2524 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2526 _player->removeSpell(spellToUnlearn);
2528 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2531 void Spell::EffectPowerDrain(uint32 i)
2533 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2534 return;
2536 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2538 if(!unitTarget)
2539 return;
2540 if(!unitTarget->isAlive())
2541 return;
2542 if(unitTarget->getPowerType() != drain_power)
2543 return;
2544 if(damage < 0)
2545 return;
2547 uint32 curPower = unitTarget->GetPower(drain_power);
2549 //add spell damage bonus
2550 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2552 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2553 uint32 power = damage;
2554 if (drain_power == POWER_MANA)
2555 power -= unitTarget->GetSpellCritDamageReduction(power);
2557 int32 new_damage;
2558 if(curPower < power)
2559 new_damage = curPower;
2560 else
2561 new_damage = power;
2563 unitTarget->ModifyPower(drain_power,-new_damage);
2565 // Don`t restore from self drain
2566 if(drain_power == POWER_MANA && m_caster != unitTarget)
2568 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2569 if(manaMultiplier==0)
2570 manaMultiplier = 1;
2572 if(Player *modOwner = m_caster->GetSpellModOwner())
2573 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2575 int32 gain = int32(new_damage * manaMultiplier);
2577 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2581 void Spell::EffectSendEvent(uint32 EffectIndex)
2584 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2586 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2587 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2590 void Spell::EffectPowerBurn(uint32 i)
2592 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2593 return;
2595 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2597 if (!unitTarget)
2598 return;
2599 if (!unitTarget->isAlive())
2600 return;
2601 if (unitTarget->getPowerType()!=powertype)
2602 return;
2603 if (damage < 0)
2604 return;
2606 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2607 if (m_spellInfo->ManaCostPercentage)
2609 uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2610 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2611 if(damage > maxdamage) damage = maxdamage;
2614 int32 curPower = int32(unitTarget->GetPower(powertype));
2616 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2617 uint32 power = damage;
2618 if (powertype == POWER_MANA)
2619 power -= unitTarget->GetSpellCritDamageReduction(power);
2621 int32 new_damage = (curPower < power) ? curPower : power;
2623 unitTarget->ModifyPower(powertype, -new_damage);
2624 float multiplier = m_spellInfo->EffectMultipleValue[i];
2626 if (Player *modOwner = m_caster->GetSpellModOwner())
2627 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2629 new_damage = int32(new_damage * multiplier);
2630 m_damage += new_damage;
2633 void Spell::EffectHeal( uint32 /*i*/ )
2635 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2637 // Try to get original caster
2638 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2640 // Skip if m_originalCaster not available
2641 if (!caster)
2642 return;
2644 int32 addhealth = damage;
2646 // Seal of Light proc
2647 if (m_spellInfo->Id == 20167)
2649 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
2650 int32 holy = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellInfo)) +
2651 caster->SpellBaseHealingBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
2652 addhealth += int32(ap * 0.15) + int32(holy * 15 / 100);
2654 // Vessel of the Naaru (Vial of the Sunwell trinket)
2655 else if (m_spellInfo->Id == 45064)
2657 // Amount of heal - depends from stacked Holy Energy
2658 int damageAmount = 0;
2659 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2660 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2661 if ((*i)->GetId() == 45062)
2662 damageAmount+=(*i)->GetModifier()->m_amount;
2663 if (damageAmount)
2664 m_caster->RemoveAurasDueToSpell(45062);
2666 addhealth += damageAmount;
2668 // Death Pact (percent heal)
2669 else if (m_spellInfo->Id==48743)
2670 addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
2671 // Swiftmend - consumes Regrowth or Rejuvenation
2672 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2674 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2675 // find most short by duration
2676 Aura *targetAura = NULL;
2677 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2679 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2680 // Regrowth or Rejuvenation 0x40 | 0x10
2681 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
2683 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2684 targetAura = *i;
2688 if (!targetAura)
2690 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
2691 return;
2693 int idx = 0;
2694 while(idx < 3)
2696 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2697 break;
2698 idx++;
2701 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2702 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2704 // Glyph of Swiftmend
2705 if (!caster->HasAura(54824))
2706 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2708 addhealth += tickheal * tickcount;
2710 else
2711 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2713 m_healing+=addhealth;
2717 void Spell::EffectHealPct( uint32 /*i*/ )
2719 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2721 // Try to get original caster
2722 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2724 // Skip if m_originalCaster not available
2725 if (!caster)
2726 return;
2728 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2729 if (Player* modOwner = m_caster->GetSpellModOwner())
2730 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2732 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2733 unitTarget->getHostileRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2737 void Spell::EffectHealMechanical( uint32 /*i*/ )
2739 // Mechanic creature type should be correctly checked by targetCreatureType field
2740 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2742 // Try to get original caster
2743 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2745 // Skip if m_originalCaster not available
2746 if (!caster)
2747 return;
2749 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2750 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2754 void Spell::EffectHealthLeech(uint32 i)
2756 if (!unitTarget)
2757 return;
2758 if (!unitTarget->isAlive())
2759 return;
2761 if (damage < 0)
2762 return;
2764 sLog.outDebug("HealthLeech :%i", damage);
2766 uint32 curHealth = unitTarget->GetHealth();
2767 damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
2768 if (curHealth < damage)
2769 damage = curHealth;
2771 float multiplier = m_spellInfo->EffectMultipleValue[i];
2773 if (Player *modOwner = m_caster->GetSpellModOwner())
2774 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2776 uint32 heal = uint32(damage*multiplier);
2777 if (m_caster->isAlive())
2779 heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
2780 m_caster->DealHeal(m_caster, heal, m_spellInfo);
2784 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2786 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2787 return;
2789 Player* player = (Player*)unitTarget;
2791 uint32 newitemid = itemtype;
2792 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype( newitemid );
2793 if(!pProto)
2795 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2796 return;
2799 // bg reward have some special in code work
2800 uint32 bgType = 0;
2801 switch(m_spellInfo->Id)
2803 case SPELL_AV_MARK_WINNER:
2804 case SPELL_AV_MARK_LOSER:
2805 bgType = BATTLEGROUND_AV;
2806 break;
2807 case SPELL_WS_MARK_WINNER:
2808 case SPELL_WS_MARK_LOSER:
2809 bgType = BATTLEGROUND_WS;
2810 break;
2811 case SPELL_AB_MARK_WINNER:
2812 case SPELL_AB_MARK_LOSER:
2813 bgType = BATTLEGROUND_AB;
2814 break;
2815 default:
2816 break;
2819 uint32 num_to_add;
2821 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2822 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2824 int32 basePoints = m_currentBasePoints[i];
2825 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2826 if (randomPoints)
2827 num_to_add = basePoints + irand(1, randomPoints);
2828 else
2829 num_to_add = basePoints + 1;
2831 else if (pProto->MaxCount == 1)
2832 num_to_add = 1;
2833 else if(player->getLevel() >= m_spellInfo->spellLevel)
2835 int32 basePoints = m_currentBasePoints[i];
2836 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2837 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2839 else
2840 num_to_add = 2;
2842 if (num_to_add < 1)
2843 num_to_add = 1;
2844 if (num_to_add > pProto->GetMaxStackSize())
2845 num_to_add = pProto->GetMaxStackSize();
2847 // init items_count to 1, since 1 item will be created regardless of specialization
2848 int items_count=1;
2849 // the chance to create additional items
2850 float additionalCreateChance=0.0f;
2851 // the maximum number of created additional items
2852 uint8 additionalMaxNum=0;
2853 // get the chance and maximum number for creating extra items
2854 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2856 // roll with this chance till we roll not to create or we create the max num
2857 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2858 ++items_count;
2861 // really will be created more items
2862 num_to_add *= items_count;
2864 // can the player store the new item?
2865 ItemPosCountVec dest;
2866 uint32 no_space = 0;
2867 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2868 if( msg != EQUIP_ERR_OK )
2870 // convert to possible store amount
2871 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2872 num_to_add -= no_space;
2873 else
2875 // if not created by another reason from full inventory or unique items amount limitation
2876 player->SendEquipError( msg, NULL, NULL );
2877 return;
2881 if(num_to_add)
2883 // create the new item and store it
2884 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2886 // was it successful? return error if not
2887 if(!pItem)
2889 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2890 return;
2893 // set the "Crafted by ..." property of the item
2894 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2895 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
2897 // send info to the client
2898 if(pItem)
2899 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
2901 // we succeeded in creating at least one item, so a levelup is possible
2902 if(bgType == 0)
2903 player->UpdateCraftSkill(m_spellInfo->Id);
2906 // for battleground marks send by mail if not add all expected
2907 if(no_space > 0 && bgType)
2909 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
2910 bg->SendRewardMarkByMail(player, newitemid, no_space);
2914 void Spell::EffectCreateItem(uint32 i)
2916 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2919 void Spell::EffectCreateItem2(uint32 i)
2921 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2922 return;
2923 Player* player = (Player*)m_caster;
2925 uint32 item_id = m_spellInfo->EffectItemType[i];
2927 DoCreateItem(i, item_id);
2929 // special case: fake item replaced by generate using spell_loot_template
2930 if (IsLootCraftingSpell(m_spellInfo))
2932 if (!player->HasItemCount(item_id, 1))
2933 return;
2935 // remove reagent
2936 uint32 count = 1;
2937 player->DestroyItemCount(item_id, count, true);
2939 // create some random items
2940 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2944 void Spell::EffectCreateRandomItem(uint32 i)
2946 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2947 return;
2948 Player* player = (Player*)m_caster;
2950 // create some random items
2951 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2954 void Spell::EffectPersistentAA(uint32 i)
2956 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2958 if (Player* modOwner = m_caster->GetSpellModOwner())
2959 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2961 int32 duration = GetSpellDuration(m_spellInfo);
2962 DynamicObject* dynObj = new DynamicObject;
2963 if (!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2965 delete dynObj;
2966 return;
2968 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2969 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2970 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2971 m_caster->AddDynObject(dynObj);
2972 m_caster->GetMap()->Add(dynObj);
2975 void Spell::EffectEnergize(uint32 i)
2977 if(!unitTarget)
2978 return;
2979 if(!unitTarget->isAlive())
2980 return;
2982 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2983 return;
2985 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2987 // Some level depends spells
2988 int level_multiplier = 0;
2989 int level_diff = 0;
2990 switch (m_spellInfo->Id)
2992 case 9512: // Restore Energy
2993 level_diff = m_caster->getLevel() - 40;
2994 level_multiplier = 2;
2995 break;
2996 case 24571: // Blood Fury
2997 level_diff = m_caster->getLevel() - 60;
2998 level_multiplier = 10;
2999 break;
3000 case 24532: // Burst of Energy
3001 level_diff = m_caster->getLevel() - 60;
3002 level_multiplier = 4;
3003 break;
3004 case 31930: // Judgements of the Wise
3005 case 48542: // Revitalize (mana restore case)
3006 case 63375: // Improved Stormstrike
3007 damage = damage * unitTarget->GetCreateMana() / 100;
3008 break;
3009 default:
3010 break;
3013 if (level_diff > 0)
3014 damage -= level_multiplier * level_diff;
3016 if(damage < 0)
3017 return;
3019 if(unitTarget->GetMaxPower(power) == 0)
3020 return;
3022 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
3024 // Mad Alchemist's Potion
3025 if (m_spellInfo->Id == 45051)
3027 // find elixirs on target
3028 uint32 elixir_mask = 0;
3029 Unit::AuraMap& Auras = unitTarget->GetAuras();
3030 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3032 uint32 spell_id = itr->second->GetId();
3033 if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
3034 elixir_mask |= mask;
3037 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3038 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
3040 // get all available elixirs by mask and spell level
3041 std::vector<uint32> elixirs;
3042 SpellElixirMap const& m_spellElixirs = sSpellMgr.GetSpellElixirMap();
3043 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
3045 if (itr->second & elixir_mask)
3047 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
3048 continue;
3050 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
3051 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
3052 continue;
3054 elixirs.push_back(itr->first);
3058 if (!elixirs.empty())
3060 // cast random elixir on target
3061 uint32 rand_spell = urand(0,elixirs.size()-1);
3062 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
3067 void Spell::EffectEnergisePct(uint32 i)
3069 if (!unitTarget)
3070 return;
3071 if (!unitTarget->isAlive())
3072 return;
3074 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
3075 return;
3077 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
3079 uint32 maxPower = unitTarget->GetMaxPower(power);
3080 if (maxPower == 0)
3081 return;
3083 uint32 gain = damage * maxPower / 100;
3084 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
3087 void Spell::SendLoot(uint64 guid, LootType loottype)
3089 Player* player = (Player*)m_caster;
3090 if (!player)
3091 return;
3093 if (gameObjTarget)
3095 if (Script->GOHello(player, gameObjTarget))
3096 return;
3098 switch (gameObjTarget->GetGoType())
3100 case GAMEOBJECT_TYPE_DOOR:
3101 case GAMEOBJECT_TYPE_BUTTON:
3102 gameObjTarget->UseDoorOrButton();
3103 player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
3104 return;
3106 case GAMEOBJECT_TYPE_QUESTGIVER:
3107 // start or end quest
3108 player->PrepareQuestMenu(guid);
3109 player->SendPreparedQuest(guid);
3110 return;
3112 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3113 // triggering linked GO
3114 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
3115 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3116 return;
3118 case GAMEOBJECT_TYPE_GOOBER:
3119 // goober_scripts can be triggered if the player don't have the quest
3120 if (gameObjTarget->GetGOInfo()->goober.eventId)
3122 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
3123 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
3126 // cast goober spell
3127 if (gameObjTarget->GetGOInfo()->goober.questId)
3128 ///Quest require to be active for GO using
3129 if (player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
3130 return;
3132 gameObjTarget->AddUniqueUse(player);
3133 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
3135 //TODO? Objective counting called without spell check but with quest objective check
3136 // if send spell id then this line will duplicate to spell casting call (double counting)
3137 // So we or have this line and not required in quest_template have reqSpellIdN
3138 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3139 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
3141 // triggering linked GO
3142 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
3143 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3145 return;
3147 case GAMEOBJECT_TYPE_CHEST:
3148 // TODO: possible must be moved to loot release (in different from linked triggering)
3149 if (gameObjTarget->GetGOInfo()->chest.eventId)
3151 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
3152 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
3155 // triggering linked GO
3156 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
3157 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3159 // Don't return, let loots been taken
3160 default:
3161 break;
3165 // Send loot
3166 player->SendLoot(guid, loottype);
3169 void Spell::EffectOpenLock(uint32 effIndex)
3171 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3173 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3174 return;
3177 Player* player = (Player*)m_caster;
3179 uint32 lockId = 0;
3180 uint64 guid = 0;
3182 // Get lockId
3183 if (gameObjTarget)
3185 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3186 // Arathi Basin banner opening !
3187 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3188 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3190 //CanUseBattleGroundObject() already called in CheckCast()
3191 // in battleground check
3192 if (BattleGround *bg = player->GetBattleGround())
3194 // check if it's correct bg
3195 if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
3196 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3197 return;
3200 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3202 //CanUseBattleGroundObject() already called in CheckCast()
3203 // in battleground check
3204 if (BattleGround *bg = player->GetBattleGround())
3206 if (bg->GetTypeID() == BATTLEGROUND_EY)
3207 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3208 return;
3211 lockId = goInfo->GetLockId();
3212 guid = gameObjTarget->GetGUID();
3214 else if (itemTarget)
3216 lockId = itemTarget->GetProto()->LockID;
3217 guid = itemTarget->GetGUID();
3219 else
3221 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3222 return;
3225 SkillType skillId = SKILL_NONE;
3226 int32 reqSkillValue = 0;
3227 int32 skillValue;
3229 SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
3230 if (res != SPELL_CAST_OK)
3232 SendCastResult(res);
3233 return;
3236 SendLoot(guid, LOOT_SKINNING);
3238 // not allow use skill grow at item base open
3239 if (!m_CastItem && skillId != SKILL_NONE)
3241 // update skill if really known
3242 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3244 if (gameObjTarget)
3246 // Allow one skill-up until respawned
3247 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3248 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3249 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3251 else if (itemTarget)
3253 // Do one skill-up
3254 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3260 void Spell::EffectSummonChangeItem(uint32 i)
3262 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3263 return;
3265 Player *player = (Player*)m_caster;
3267 // applied only to using item
3268 if (!m_CastItem)
3269 return;
3271 // ... only to item in own inventory/bank/equip_slot
3272 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3273 return;
3275 uint32 newitemid = m_spellInfo->EffectItemType[i];
3276 if (!newitemid)
3277 return;
3279 uint16 pos = m_CastItem->GetPos();
3281 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3282 if (!pNewItem)
3283 return;
3285 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3287 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3288 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3291 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3293 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3294 player->DurabilityLoss(pNewItem, loosePercent);
3297 if (player->IsInventoryPos(pos))
3299 ItemPosCountVec dest;
3300 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3301 if (msg == EQUIP_ERR_OK)
3303 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3305 // prevent crash at access and unexpected charges counting with item update queue corrupt
3306 if (m_CastItem==m_targets.getItemTarget())
3307 m_targets.setItemTarget(NULL);
3309 m_CastItem = NULL;
3311 player->StoreItem( dest, pNewItem, true);
3312 return;
3315 else if (player->IsBankPos (pos))
3317 ItemPosCountVec dest;
3318 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3319 if (msg == EQUIP_ERR_OK)
3321 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3323 // prevent crash at access and unexpected charges counting with item update queue corrupt
3324 if (m_CastItem==m_targets.getItemTarget())
3325 m_targets.setItemTarget(NULL);
3327 m_CastItem = NULL;
3329 player->BankItem( dest, pNewItem, true);
3330 return;
3333 else if (player->IsEquipmentPos (pos))
3335 uint16 dest;
3336 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3337 if (msg == EQUIP_ERR_OK)
3339 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3341 // prevent crash at access and unexpected charges counting with item update queue corrupt
3342 if (m_CastItem==m_targets.getItemTarget())
3343 m_targets.setItemTarget(NULL);
3345 m_CastItem = NULL;
3347 player->EquipItem( dest, pNewItem, true);
3348 player->AutoUnequipOffhandIfNeed();
3349 return;
3353 // fail
3354 delete pNewItem;
3357 void Spell::EffectProficiency(uint32 /*i*/)
3359 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3360 return;
3361 Player *p_target = (Player*)unitTarget;
3363 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3364 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3366 p_target->AddWeaponProficiency(subClassMask);
3367 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3369 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3371 p_target->AddArmorProficiency(subClassMask);
3372 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3376 void Spell::EffectApplyAreaAura(uint32 i)
3378 if (!unitTarget)
3379 return;
3380 if (!unitTarget->isAlive())
3381 return;
3383 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3384 unitTarget->AddAura(Aur);
3387 void Spell::EffectSummonType(uint32 i)
3389 uint32 prop_id = m_spellInfo->EffectMiscValueB[i];
3390 SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
3391 if(!summon_prop)
3393 sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3394 return;
3397 switch(summon_prop->Group)
3399 // faction handled later on, or loaded from template
3400 case SUMMON_PROP_GROUP_WILD:
3401 case SUMMON_PROP_GROUP_FRIENDLY:
3403 switch(summon_prop->Type)
3405 case SUMMON_PROP_TYPE_OTHER:
3407 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3408 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3409 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3410 if(prop_id == 121 || prop_id == 647)
3411 EffectSummonTotem(i);
3412 else
3413 EffectSummonWild(i, summon_prop->FactionId);
3414 break;
3416 case SUMMON_PROP_TYPE_SUMMON:
3417 case SUMMON_PROP_TYPE_GUARDIAN:
3418 case SUMMON_PROP_TYPE_ARMY:
3419 case SUMMON_PROP_TYPE_DK:
3420 case SUMMON_PROP_TYPE_CONSTRUCT:
3422 // JC golems - 32804, etc -- fits much better totem AI
3423 if(m_spellInfo->SpellIconID == 2056)
3424 EffectSummonTotem(i);
3425 if(prop_id == 832) // scrapbot
3426 EffectSummonWild(i, summon_prop->FactionId);
3427 else
3428 EffectSummonGuardian(i, summon_prop->FactionId);
3429 break;
3431 case SUMMON_PROP_TYPE_TOTEM:
3432 EffectSummonTotem(i, summon_prop->Slot);
3433 break;
3434 case SUMMON_PROP_TYPE_CRITTER:
3435 EffectSummonCritter(i, summon_prop->FactionId);
3436 break;
3437 case SUMMON_PROP_TYPE_PHASING:
3438 case SUMMON_PROP_TYPE_LIGHTWELL:
3439 case SUMMON_PROP_TYPE_REPAIR_BOT:
3440 EffectSummonWild(i, summon_prop->FactionId);
3441 break;
3442 case SUMMON_PROP_TYPE_SIEGE_VEH:
3443 case SUMMON_PROP_TYPE_DRAKE_VEH:
3444 // TODO
3445 // EffectSummonVehicle(i);
3446 break;
3447 default:
3448 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
3449 break;
3451 break;
3453 case SUMMON_PROP_GROUP_PETS:
3455 // FIXME : multiple summons - not yet supported as pet
3456 //1562 - force of nature - sid 33831
3457 //1161 - feral spirit - sid 51533
3458 if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
3459 EffectSummonGuardian(i, summon_prop->FactionId);
3460 else
3461 EffectSummon(i);
3462 break;
3464 case SUMMON_PROP_GROUP_CONTROLLABLE:
3466 // no type here
3467 // maybe wrong - but thats the handler currently used for those
3468 EffectSummonGuardian(i, summon_prop->FactionId);
3469 break;
3471 case SUMMON_PROP_GROUP_VEHICLE:
3473 // TODO
3474 // EffectSummonVehicle(i);
3475 break;
3477 default:
3478 sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
3479 break;
3483 void Spell::EffectSummon(uint32 i)
3485 if (m_caster->GetPetGUID())
3486 return;
3488 if (!unitTarget)
3489 return;
3490 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3491 if (!pet_entry)
3492 return;
3493 uint32 level = m_caster->getLevel();
3494 Pet* spawnCreature = new Pet(SUMMON_PET);
3496 int32 duration = GetSpellDuration(m_spellInfo);
3497 if(Player* modOwner = m_caster->GetSpellModOwner())
3498 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3500 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3502 // Summon in dest location
3503 float x, y, z;
3504 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3506 x = m_targets.m_destX;
3507 y = m_targets.m_destY;
3508 z = m_targets.m_destZ;
3509 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3512 // set timer for unsummon
3513 if (duration > 0)
3514 spawnCreature->SetDuration(duration);
3516 return;
3519 Map *map = m_caster->GetMap();
3520 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3521 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3522 m_spellInfo->EffectMiscValue[i], pet_number))
3524 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3525 delete spawnCreature;
3526 return;
3529 // Summon in dest location
3530 float x, y, z;
3531 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3533 x = m_targets.m_destX;
3534 y = m_targets.m_destY;
3535 z = m_targets.m_destZ;
3537 else
3538 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3540 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3542 if (!spawnCreature->IsPositionValid())
3544 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3545 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3546 delete spawnCreature;
3547 return;
3550 // set timer for unsummon
3551 if (duration > 0)
3552 spawnCreature->SetDuration(duration);
3554 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3555 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3556 spawnCreature->setPowerType(POWER_MANA);
3557 spawnCreature->setFaction(m_caster->getFaction());
3558 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3559 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3560 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3561 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3562 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3563 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3564 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3565 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3567 spawnCreature->InitStatsForLevel(level, m_caster);
3569 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3571 spawnCreature->AIM_Initialize();
3572 spawnCreature->InitPetCreateSpells();
3573 spawnCreature->InitLevelupSpellsForLevel();
3574 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3575 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3577 std::string name = m_caster->GetName();
3578 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3579 spawnCreature->SetName( name );
3581 map->Add((Creature*)spawnCreature);
3583 m_caster->SetPet(spawnCreature);
3585 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3587 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3588 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3589 ((Player*)m_caster)->PetSpellInitialize();
3593 void Spell::EffectLearnSpell(uint32 i)
3595 if (!unitTarget)
3596 return;
3598 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3600 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3601 EffectLearnPetSpell(i);
3603 return;
3606 Player *player = (Player*)unitTarget;
3608 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3609 player->learnSpell(spellToLearn,false);
3611 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3614 void Spell::EffectDispel(uint32 i)
3616 if (!unitTarget)
3617 return;
3619 // Fill possible dispell list
3620 std::vector <Aura *> dispel_list;
3622 // Create dispel mask by dispel type
3623 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3624 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3625 Unit::AuraMap const& auras = unitTarget->GetAuras();
3626 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3628 Aura *aur = (*itr).second;
3629 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3631 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3633 bool positive = true;
3634 if (!aur->IsPositive())
3635 positive = false;
3636 else
3637 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3639 // do not remove positive auras if friendly target
3640 // negative auras if non-friendly target
3641 if (positive == unitTarget->IsFriendlyTo(m_caster))
3642 continue;
3644 // Add aura to dispel list (all stack cases)
3645 for(int k = 0; k < aur->GetStackAmount(); ++k)
3646 dispel_list.push_back(aur);
3649 // Ok if exist some buffs for dispel try dispel it
3650 if (!dispel_list.empty())
3652 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3653 std::list < uint32 > fail_list; // spell_id
3655 // some spells have effect value = 0 and all from its by meaning expect 1
3656 if(!damage)
3657 damage = 1;
3659 // Dispell N = damage buffs (or while exist buffs for dispel)
3660 for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
3662 // Random select buff for dispel
3663 std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
3664 std::advance(dispel_itr,urand(0, dispel_list.size()-1));
3666 Aura *aur = *dispel_itr;
3668 // remove entry from dispel_list
3669 dispel_list.erase(dispel_itr);
3671 SpellEntry const* spellInfo = aur->GetSpellProto();
3672 // Base dispel chance
3673 // TODO: possible chance depend from spell level??
3674 int32 miss_chance = 0;
3675 // Apply dispel mod from aura caster
3676 if (Unit *caster = aur->GetCaster())
3678 if ( Player* modOwner = caster->GetSpellModOwner() )
3679 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3681 // Try dispel
3682 if (roll_chance_i(miss_chance))
3683 fail_list.push_back(spellInfo->Id);
3684 else
3685 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3687 // Send success log and really remove auras
3688 if (!success_list.empty())
3690 int32 count = success_list.size();
3691 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3692 data.append(unitTarget->GetPackGUID()); // Victim GUID
3693 data.append(m_caster->GetPackGUID()); // Caster GUID
3694 data << uint32(m_spellInfo->Id); // Dispel spell id
3695 data << uint8(0); // not used
3696 data << uint32(count); // count
3697 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3699 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3700 data << uint32(spellInfo->Id); // Spell Id
3701 data << uint8(0); // 0 - dispeled !=0 cleansed
3702 unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3704 m_caster->SendMessageToSet(&data, true);
3706 // On success dispel
3707 // Devour Magic
3708 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3710 int32 heal_amount = m_spellInfo->CalculateSimpleValue(1);
3711 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
3714 // Send fail log to client
3715 if (!fail_list.empty())
3717 // Failed to dispell
3718 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3719 data << uint64(m_caster->GetGUID()); // Caster GUID
3720 data << uint64(unitTarget->GetGUID()); // Victim GUID
3721 data << uint32(m_spellInfo->Id); // Dispell spell id
3722 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3723 data << uint32(*j); // Spell Id
3724 m_caster->SendMessageToSet(&data, true);
3729 void Spell::EffectDualWield(uint32 /*i*/)
3731 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3732 ((Player*)unitTarget)->SetCanDualWield(true);
3735 void Spell::EffectPull(uint32 /*i*/)
3737 // TODO: create a proper pull towards distract spell center for distract
3738 sLog.outDebug("WORLD: Spell Effect DUMMY");
3741 void Spell::EffectDistract(uint32 /*i*/)
3743 // Check for possible target
3744 if (!unitTarget || unitTarget->isInCombat())
3745 return;
3747 // target must be OK to do this
3748 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3749 return;
3751 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3753 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3755 // For players just turn them
3756 WorldPacket data;
3757 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3758 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3759 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3761 else
3763 // Set creature Distracted, Stop it, And turn it
3764 unitTarget->SetOrientation(angle);
3765 unitTarget->StopMoving();
3766 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
3770 void Spell::EffectPickPocket(uint32 /*i*/)
3772 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3773 return;
3775 // victim must be creature and attackable
3776 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
3777 return;
3779 // victim have to be alive and humanoid or undead
3780 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3782 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3784 if (chance > irand(0, 19))
3786 // Stealing successful
3787 //sLog.outDebug("Sending loot from pickpocket");
3788 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3790 else
3792 // Reveal action + get attack
3793 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3794 if (((Creature*)unitTarget)->AI())
3795 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3800 void Spell::EffectAddFarsight(uint32 i)
3802 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3803 return;
3805 int32 duration = GetSpellDuration(m_spellInfo);
3806 DynamicObject* dynObj = new DynamicObject;
3808 // set radius to 0: spell not expected to work as persistent aura
3809 if(!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
3811 delete dynObj;
3812 return;
3814 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3815 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3816 m_caster->AddDynObject(dynObj);
3817 m_caster->GetMap()->Add(dynObj);
3818 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3821 void Spell::EffectSummonWild(uint32 i, uint32 forceFaction)
3823 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3824 if (!creature_entry)
3825 return;
3827 uint32 level = m_caster->getLevel();
3829 // level of creature summoned using engineering item based at engineering skill level
3830 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3832 ItemPrototype const *proto = m_CastItem->GetProto();
3833 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3835 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3836 if (skill202)
3837 level = skill202/5;
3841 // select center of summon position
3842 float center_x = m_targets.m_destX;
3843 float center_y = m_targets.m_destY;
3844 float center_z = m_targets.m_destZ;
3846 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3847 int32 duration = GetSpellDuration(m_spellInfo);
3848 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3850 int32 amount = damage > 0 ? damage : 1;
3852 for(int32 count = 0; count < amount; ++count)
3854 float px, py, pz;
3855 // If dest location if present
3856 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3858 // Summon 1 unit in dest location
3859 if (count == 0)
3861 px = m_targets.m_destX;
3862 py = m_targets.m_destY;
3863 pz = m_targets.m_destZ;
3865 // Summon in random point all other units if location present
3866 else
3867 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3869 // Summon if dest location not present near caster
3870 else
3871 m_caster->GetClosePoint(px, py, pz, 3.0f);
3873 if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
3875 summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3876 summon->SetCreatorGUID(m_caster->GetGUID());
3878 if(forceFaction)
3879 summon->setFaction(forceFaction);
3884 void Spell::EffectSummonGuardian(uint32 i, uint32 forceFaction)
3886 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3887 if (!pet_entry)
3888 return;
3890 // in another case summon new
3891 uint32 level = m_caster->getLevel();
3893 // level of pet summoned using engineering item based at engineering skill level
3894 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
3896 ItemPrototype const *proto = m_CastItem->GetProto();
3897 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3899 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3900 if (skill202)
3902 level = skill202 / 5;
3907 // select center of summon position
3908 float center_x = m_targets.m_destX;
3909 float center_y = m_targets.m_destY;
3910 float center_z = m_targets.m_destZ;
3912 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3913 int32 duration = GetSpellDuration(m_spellInfo);
3914 if(Player* modOwner = m_caster->GetSpellModOwner())
3915 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3917 int32 amount = damage > 0 ? damage : 1;
3919 for(int32 count = 0; count < amount; ++count)
3921 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3923 Map *map = m_caster->GetMap();
3924 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3925 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3926 m_spellInfo->EffectMiscValue[i], pet_number))
3928 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[i]);
3929 delete spawnCreature;
3930 return;
3933 float px, py, pz;
3934 // If dest location if present
3935 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3937 // Summon 1 unit in dest location
3938 if (count == 0)
3940 px = m_targets.m_destX;
3941 py = m_targets.m_destY;
3942 pz = m_targets.m_destZ;
3944 // Summon in random point all other units if location present
3945 else
3946 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3948 // Summon if dest location not present near caster
3949 else
3950 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
3952 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
3954 if (!spawnCreature->IsPositionValid())
3956 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3957 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3958 delete spawnCreature;
3959 return;
3962 if (duration > 0)
3963 spawnCreature->SetDuration(duration);
3965 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3966 spawnCreature->setPowerType(POWER_MANA);
3967 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
3968 spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
3969 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3970 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3971 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3972 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3973 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3975 spawnCreature->InitStatsForLevel(level, m_caster);
3976 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3978 spawnCreature->AIM_Initialize();
3980 m_caster->AddGuardian(spawnCreature);
3982 map->Add((Creature*)spawnCreature);
3986 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3988 if (!unitTarget)
3989 return;
3991 if (unitTarget->isInFlight())
3992 return;
3994 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3996 float fx, fy, fz;
3997 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
3999 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
4002 void Spell::EffectLearnSkill(uint32 i)
4004 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4005 return;
4007 if (damage < 0)
4008 return;
4010 uint32 skillid = m_spellInfo->EffectMiscValue[i];
4011 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
4012 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4015 void Spell::EffectAddHonor(uint32 /*i*/)
4017 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4018 return;
4020 // not scale value for item based reward (/10 value expected)
4021 if (m_CastItem)
4023 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage / 10);
4024 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
4025 return;
4028 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4029 if (damage <= 50)
4031 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
4032 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
4033 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
4035 else
4037 //maybe we have correct honor_gain in damage already
4038 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
4039 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
4043 void Spell::EffectTradeSkill(uint32 /*i*/)
4045 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4046 return;
4047 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4048 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4049 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4052 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
4054 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4055 return;
4056 if (!itemTarget)
4057 return;
4059 Player* p_caster = (Player*)m_caster;
4061 // not grow at item use at item case
4062 p_caster->UpdateCraftSkill(m_spellInfo->Id);
4064 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
4065 if (!enchant_id)
4066 return;
4068 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4069 if (!pEnchant)
4070 return;
4072 // item can be in trade slot and have owner diff. from caster
4073 Player* item_owner = itemTarget->GetOwner();
4074 if (!item_owner)
4075 return;
4077 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4079 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4080 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4081 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4082 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4085 // remove old enchanting before applying new if equipped
4086 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
4088 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4090 // add new enchanting if equipped
4091 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
4094 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
4096 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4097 return;
4098 if (!itemTarget)
4099 return;
4101 Player* p_caster = (Player*)m_caster;
4103 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
4104 if (!enchant_id)
4105 return;
4107 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4108 if (!pEnchant)
4109 return;
4111 // support only enchantings with add socket in this slot
4113 bool add_socket = false;
4114 for(int i = 0; i < 3; ++i)
4116 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
4118 add_socket = true;
4119 break;
4122 if (!add_socket)
4124 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.",
4125 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
4126 return;
4130 // item can be in trade slot and have owner diff. from caster
4131 Player* item_owner = itemTarget->GetOwner();
4132 if (!item_owner)
4133 return;
4135 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4137 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4138 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4139 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4140 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4143 // remove old enchanting before applying new if equipped
4144 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4146 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4148 // add new enchanting if equipped
4149 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4152 void Spell::EffectEnchantItemTmp(uint32 i)
4154 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4155 return;
4157 Player* p_caster = (Player*)m_caster;
4159 // Rockbiter Weapon apply to both weapon
4160 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000))
4162 uint32 spell_id = 0;
4164 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4165 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4166 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4167 switch(damage)
4169 // Rank 1
4170 case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4171 // Rank 2
4172 case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
4173 case 5: spell_id = 36751; break; // 20%
4174 // Rank 3
4175 case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
4176 case 7: spell_id = 36755; break; // 20%
4177 // Rank 4
4178 case 9: spell_id = 36761; break; // 0% [ 7% == 6]
4179 case 10: spell_id = 36758; break; // 14%
4180 case 11: spell_id = 36760; break; // 20%
4181 default:
4182 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
4183 return;
4187 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
4188 if (!spellInfo)
4190 sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
4191 return;
4194 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
4196 if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
4198 if (item->IsFitToSpellRequirements(m_spellInfo))
4200 Spell *spell = new Spell(m_caster, spellInfo, true);
4201 SpellCastTargets targets;
4202 targets.setItemTarget( item );
4203 spell->prepare(&targets);
4207 return;
4210 if (!itemTarget)
4211 return;
4213 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
4215 if (!enchant_id)
4217 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
4218 return;
4221 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4222 if(!pEnchant)
4224 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
4225 return;
4228 // select enchantment duration
4229 uint32 duration;
4231 // rogue family enchantments exception by duration
4232 if(m_spellInfo->Id == 38615)
4233 duration = 1800; // 30 mins
4234 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4235 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4236 duration = 3600; // 1 hour
4237 // shaman family enchantments
4238 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4239 duration = 1800; // 30 mins
4240 // other cases with this SpellVisual already selected
4241 else if(m_spellInfo->SpellVisual[0] == 215)
4242 duration = 1800; // 30 mins
4243 // some fishing pole bonuses
4244 else if(m_spellInfo->SpellVisual[0] == 563)
4245 duration = 600; // 10 mins
4246 // shaman rockbiter enchantments
4247 else if(m_spellInfo->SpellVisual[0] == 0)
4248 duration = 1800; // 30 mins
4249 else if(m_spellInfo->Id == 29702)
4250 duration = 300; // 5 mins
4251 else if(m_spellInfo->Id == 37360)
4252 duration = 300; // 5 mins
4253 // default case
4254 else
4255 duration = 3600; // 1 hour
4257 // item can be in trade slot and have owner diff. from caster
4258 Player* item_owner = itemTarget->GetOwner();
4259 if(!item_owner)
4260 return;
4262 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4264 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4265 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4266 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4267 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4270 // remove old enchanting before applying new if equipped
4271 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4273 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4275 // add new enchanting if equipped
4276 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4279 void Spell::EffectTameCreature(uint32 /*i*/)
4281 // Caster must be player, checked in Spell::CheckCast
4282 // Spell can be triggered, we need to check original caster prior to caster
4283 Player* plr = (Player*)(m_originalCaster ? m_originalCaster : m_caster);
4285 Creature* creatureTarget = (Creature*)unitTarget;
4287 // cast finish successfully
4288 //SendChannelUpdate(0);
4289 finish();
4291 Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4292 if(!pet) // in versy specific state like near world end/etc.
4293 return;
4295 // "kill" original creature
4296 creatureTarget->ForcedDespawn();
4298 uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel();
4300 // prepare visual effect for levelup
4301 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4303 // add to world
4304 pet->GetMap()->Add((Creature*)pet);
4306 // visual effect for levelup
4307 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4309 // caster have pet now
4310 plr->SetPet(pet);
4312 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4313 plr->PetSpellInitialize();
4316 void Spell::EffectSummonPet(uint32 i)
4318 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4320 Pet *OldSummon = m_caster->GetPet();
4322 // if pet requested type already exist
4323 if( OldSummon )
4325 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4327 // pet in corpse state can't be summoned
4328 if( OldSummon->isDead() )
4329 return;
4331 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4333 float px, py, pz;
4334 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4336 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4337 m_caster->GetMap()->Add((Creature*)OldSummon);
4339 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4341 ((Player*)m_caster)->PetSpellInitialize();
4343 return;
4346 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4347 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4348 else
4349 return;
4352 Pet* NewSummon = new Pet;
4354 // petentry==0 for hunter "call pet" (current pet summoned if any)
4355 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
4357 if(NewSummon->getPetType() == SUMMON_PET)
4359 // Remove Demonic Sacrifice auras (known pet)
4360 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4361 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4363 if((*itr)->GetModifier()->m_miscvalue == 2228)
4365 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4366 itr = auraClassScripts.begin();
4368 else
4369 ++itr;
4373 return;
4376 // not error in case fail hunter call pet
4377 if(!petentry)
4379 delete NewSummon;
4380 return;
4383 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4385 if(!cInfo)
4387 sLog.outError("EffectSummonPet: creature entry %u not found.", petentry);
4388 delete NewSummon;
4389 return;
4392 Map *map = m_caster->GetMap();
4393 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4394 if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4395 petentry, pet_number))
4397 delete NewSummon;
4398 return;
4401 float px, py, pz;
4402 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4404 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4406 if(!NewSummon->IsPositionValid())
4408 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4409 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4410 delete NewSummon;
4411 return;
4414 uint32 petlevel = m_caster->getLevel();
4415 NewSummon->setPetType(SUMMON_PET);
4417 uint32 faction = m_caster->getFaction();
4418 if(m_caster->GetTypeId() == TYPEID_UNIT)
4420 if ( ((Creature*)m_caster)->isTotem() )
4421 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4422 else
4423 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4426 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4427 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4428 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4429 NewSummon->setFaction(faction);
4430 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4431 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4432 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4433 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4434 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4435 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4437 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4438 // this enables pet details window (Shift+P)
4440 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4441 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4442 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
4444 if(m_caster->IsPvP())
4445 NewSummon->SetPvP(true);
4447 NewSummon->InitStatsForLevel(petlevel, m_caster);
4448 NewSummon->InitPetCreateSpells();
4449 NewSummon->InitLevelupSpellsForLevel();
4450 NewSummon->InitTalentForLevel();
4452 if(NewSummon->getPetType() == SUMMON_PET)
4454 // Remove Demonic Sacrifice auras (new pet)
4455 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4456 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4458 if((*itr)->GetModifier()->m_miscvalue == 2228)
4460 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4461 itr = auraClassScripts.begin();
4463 else
4464 ++itr;
4467 // generate new name for summon pet
4468 std::string new_name = sObjectMgr.GeneratePetName(petentry);
4469 if(!new_name.empty())
4470 NewSummon->SetName(new_name);
4472 else if(NewSummon->getPetType() == HUNTER_PET)
4474 NewSummon->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
4475 NewSummon->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED);
4478 NewSummon->AIM_Initialize();
4479 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4480 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4482 map->Add((Creature*)NewSummon);
4484 m_caster->SetPet(NewSummon);
4485 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4487 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4489 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4490 ((Player*)m_caster)->PetSpellInitialize();
4494 void Spell::EffectLearnPetSpell(uint32 i)
4496 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4497 return;
4499 Player *_player = (Player*)m_caster;
4501 Pet *pet = _player->GetPet();
4502 if(!pet)
4503 return;
4504 if(!pet->isAlive())
4505 return;
4507 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4508 if(!learn_spellproto)
4509 return;
4511 pet->learnSpell(learn_spellproto->Id);
4513 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4514 _player->PetSpellInitialize();
4517 void Spell::EffectTaunt(uint32 /*i*/)
4519 if (!unitTarget)
4520 return;
4522 // this effect use before aura Taunt apply for prevent taunt already attacking target
4523 // for spell as marked "non effective at already attacking target"
4524 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4526 if (unitTarget->getVictim()==m_caster)
4528 SendCastResult(SPELL_FAILED_DONT_REPORT);
4529 return;
4533 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4534 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4535 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4538 void Spell::EffectWeaponDmg(uint32 i)
4540 if(!unitTarget)
4541 return;
4542 if(!unitTarget->isAlive())
4543 return;
4545 // multiple weapon dmg effect workaround
4546 // execute only the last weapon damage
4547 // and handle all effects at once
4548 for (int j = 0; j < 3; ++j)
4550 switch(m_spellInfo->Effect[j])
4552 case SPELL_EFFECT_WEAPON_DAMAGE:
4553 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4554 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4555 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4556 if (j < i) // we must calculate only at last weapon effect
4557 return;
4558 break;
4562 // some spell specific modifiers
4563 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4565 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4566 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4567 bool normalized = false;
4569 int32 spell_bonus = 0; // bonus specific for spell
4570 switch(m_spellInfo->SpellFamilyName)
4572 case SPELLFAMILY_WARRIOR:
4574 // Devastate bonus and sunder armor refresh
4575 if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4577 uint32 stack = 0;
4578 // Need refresh all Sunder Armor auras from this caster
4579 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4580 SpellEntry const *spellInfo;
4581 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4583 spellInfo = (*itr).second->GetSpellProto();
4584 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4585 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4586 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4588 (*itr).second->RefreshAura();
4589 stack = (*itr).second->GetStackAmount();
4590 break;
4593 if (stack)
4594 spell_bonus += stack * CalculateDamage(2, unitTarget);
4595 if (!stack || stack < spellInfo->StackAmount)
4596 // Devastate causing Sunder Armor Effect
4597 // and no need to cast over max stack amount
4598 m_caster->CastSpell(unitTarget, 58567, true);
4600 break;
4602 case SPELLFAMILY_ROGUE:
4604 // Mutilate (for each hand)
4605 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4607 bool found = false;
4608 // fast check
4609 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4610 found = true;
4611 // full aura scan
4612 else
4614 Unit::AuraMap const& auras = unitTarget->GetAuras();
4615 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4617 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4619 found = true;
4620 break;
4625 if(found)
4626 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4628 // Fan of Knives
4629 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4631 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
4632 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4633 totalDamagePercentMod *= 1.5f; // 150% to daggers
4635 break;
4637 case SPELLFAMILY_PALADIN:
4639 // Judgement of Command - receive benefit from Spell Damage and Attack Power
4640 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000000000))
4642 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
4643 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
4644 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
4645 spell_bonus += int32(ap * 0.08f) + int32(holy * 13 / 100);
4647 break;
4649 case SPELLFAMILY_SHAMAN:
4651 // Skyshatter Harness item set bonus
4652 // Stormstrike
4653 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4655 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4656 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4658 // Stormstrike AP Buff
4659 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4661 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4662 break;
4666 break;
4668 case SPELLFAMILY_DEATHKNIGHT:
4670 // Blood Strike, Heart Strike, Obliterate
4671 // Blood-Caked Strike, Scourge Strike
4672 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
4673 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
4675 uint32 count = 0;
4676 Unit::AuraMap const& auras = unitTarget->GetAuras();
4677 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4679 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
4680 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
4681 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
4682 ++count;
4685 if (count)
4687 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4688 float bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? 0 : 2, unitTarget) / 100.0f;
4689 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4690 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
4691 m_spellInfo->SpellIconID == 1736)
4692 bonus /= 2.0f;
4694 totalDamagePercentMod *= 1.0f + bonus;
4697 // Glyph of Blood Strike
4698 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000) &&
4699 m_caster->HasAura(59332) &&
4700 unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
4702 totalDamagePercentMod *= 1.2f; // 120% if snared
4704 // Glyph of Death Strike
4705 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010) &&
4706 m_caster->HasAura(59336))
4708 int32 rp = m_caster->GetPower(POWER_RUNIC_POWER) / 10;
4709 if(rp > 25)
4710 rp = 25;
4711 totalDamagePercentMod *= 1.0f + rp / 100.0f;
4713 // Glyph of Plague Strike
4714 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001) &&
4715 m_caster->HasAura(58657) )
4717 totalDamagePercentMod *= 1.2f;
4719 break;
4723 int32 fixed_bonus = 0;
4724 for (int j = 0; j < 3; ++j)
4726 switch(m_spellInfo->Effect[j])
4728 case SPELL_EFFECT_WEAPON_DAMAGE:
4729 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4730 fixed_bonus += CalculateDamage(j, unitTarget);
4731 break;
4732 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4733 fixed_bonus += CalculateDamage(j, unitTarget);
4734 normalized = true;
4735 break;
4736 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4737 weaponDamagePercentMod *= float(CalculateDamage(j, unitTarget)) / 100.0f;
4739 // applied only to prev.effects fixed damage
4740 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4741 break;
4742 default:
4743 break; // not weapon damage effect, just skip
4747 // apply weaponDamagePercentMod to spell bonus also
4748 if(spellBonusNeedWeaponDamagePercentMod)
4749 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4751 // non-weapon damage
4752 int32 bonus = spell_bonus + fixed_bonus;
4754 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4755 if(bonus)
4757 UnitMods unitMod;
4758 switch(m_attackType)
4760 default:
4761 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4762 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4763 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4766 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4767 bonus = int32(bonus*weapon_total_pct);
4770 // + weapon damage with applied weapon% dmg to base weapon damage in call
4771 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4773 // total damage
4774 bonus = int32(bonus*totalDamagePercentMod);
4776 // prevent negative damage
4777 m_damage+= uint32(bonus > 0 ? bonus : 0);
4779 // Hemorrhage
4780 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
4782 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4783 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4785 // Mangle (Cat): CP
4786 else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
4788 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4789 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4792 // take ammo
4793 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4795 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
4797 // wands don't have ammo
4798 if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
4799 return;
4801 if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
4803 if(pItem->GetMaxStackCount()==1)
4805 // decrease durability for non-stackable throw weapon
4806 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4808 else
4810 // decrease items amount for stackable throw weapon
4811 uint32 count = 1;
4812 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4815 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4816 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4820 void Spell::EffectThreat(uint32 /*i*/)
4822 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4823 return;
4825 if(!unitTarget->CanHaveThreatList())
4826 return;
4828 unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
4831 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4833 if(!unitTarget)
4834 return;
4835 if(!unitTarget->isAlive())
4836 return;
4838 uint32 heal = m_caster->GetMaxHealth();
4840 m_healing += heal;
4843 void Spell::EffectInterruptCast(uint32 /*i*/)
4845 if(!unitTarget)
4846 return;
4847 if(!unitTarget->isAlive())
4848 return;
4850 // TODO: not all spells that used this effect apply cooldown at school spells
4851 // also exist case: apply cooldown to interrupted cast only and to all spells
4852 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
4854 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
4856 SpellEntry const* curSpellInfo = spell->m_spellInfo;
4857 // check if we can interrupt spell
4858 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4860 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
4861 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
4867 void Spell::EffectSummonObjectWild(uint32 i)
4869 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4871 GameObject* pGameObj = new GameObject;
4873 WorldObject* target = focusObject;
4874 if( !target )
4875 target = m_caster;
4877 float x, y, z;
4878 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4880 x = m_targets.m_destX;
4881 y = m_targets.m_destY;
4882 z = m_targets.m_destZ;
4884 else
4885 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4887 Map *map = target->GetMap();
4889 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4890 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4892 delete pGameObj;
4893 return;
4896 int32 duration = GetSpellDuration(m_spellInfo);
4898 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4899 pGameObj->SetSpellId(m_spellInfo->Id);
4901 // Wild object not have owner and check clickable by players
4902 map->Add(pGameObj);
4904 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
4906 Player *pl = (Player*)m_caster;
4907 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4909 switch(pGameObj->GetMapId())
4911 case 489: //WS
4913 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4915 uint32 team = ALLIANCE;
4917 if(pl->GetTeam() == team)
4918 team = HORDE;
4920 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4922 break;
4924 case 566: //EY
4926 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4928 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4930 break;
4935 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
4937 GameObject* linkedGO = new GameObject;
4938 if(linkedGO->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4939 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4941 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4942 linkedGO->SetSpellId(m_spellInfo->Id);
4944 // Wild object not have owner and check clickable by players
4945 map->Add(linkedGO);
4947 else
4949 delete linkedGO;
4950 linkedGO = NULL;
4951 return;
4956 void Spell::EffectScriptEffect(uint32 effIndex)
4958 // TODO: we must implement hunter pet summon at login there (spell 6962)
4960 switch(m_spellInfo->SpellFamilyName)
4962 case SPELLFAMILY_GENERIC:
4964 switch(m_spellInfo->Id)
4966 // Bending Shinbone
4967 case 8856:
4969 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4970 return;
4972 uint32 spell_id = 0;
4973 switch(urand(1, 5))
4975 case 1: spell_id = 8854; break;
4976 default: spell_id = 8855; break;
4979 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4980 return;
4982 // Piccolo of the Flaming Fire
4983 case 17512:
4985 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4986 return;
4987 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4988 return;
4990 // Escape artist
4991 case 20589:
4993 if(!unitTarget)
4994 return;
4996 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4997 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4998 return;
5000 // Brittle Armor - need remove one 24575 Brittle Armor aura
5001 case 24590:
5002 unitTarget->RemoveSingleSpellAurasFromStack(24575);
5003 return;
5004 // PX-238 Winter Wondervolt TRAP
5005 case 26275:
5007 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
5009 // check presence
5010 for(int j = 0; j < 4; ++j)
5011 if(unitTarget->HasAura(spells[j],0))
5012 return;
5014 // select spell
5015 uint32 iTmpSpellId = spells[urand(0,3)];
5017 // cast
5018 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
5019 return;
5021 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5022 case 26465:
5023 unitTarget->RemoveSingleSpellAurasFromStack(26464);
5024 return;
5025 // Orb teleport spells
5026 case 25140:
5027 case 25143:
5028 case 25650:
5029 case 25652:
5030 case 29128:
5031 case 29129:
5032 case 35376:
5033 case 35727:
5035 if(!unitTarget)
5036 return;
5038 uint32 spellid;
5039 switch(m_spellInfo->Id)
5041 case 25140: spellid = 32571; break;
5042 case 25143: spellid = 32572; break;
5043 case 25650: spellid = 30140; break;
5044 case 25652: spellid = 30141; break;
5045 case 29128: spellid = 32568; break;
5046 case 29129: spellid = 32569; break;
5047 case 35376: spellid = 25649; break;
5048 case 35727: spellid = 35730; break;
5049 default:
5050 return;
5053 unitTarget->CastSpell(unitTarget,spellid,false);
5054 return;
5056 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
5057 case 22539:
5058 case 22972:
5059 case 22975:
5060 case 22976:
5061 case 22977:
5062 case 22978:
5063 case 22979:
5064 case 22980:
5065 case 22981:
5066 case 22982:
5067 case 22983:
5068 case 22984:
5069 case 22985:
5071 if(!unitTarget || !unitTarget->isAlive())
5072 return;
5074 // Onyxia Scale Cloak
5075 if(unitTarget->GetDummyAura(22683))
5076 return;
5078 // Shadow Flame
5079 m_caster->CastSpell(unitTarget, 22682, true);
5080 return;
5082 // Summon Black Qiraji Battle Tank
5083 case 26656:
5085 if(!unitTarget)
5086 return;
5088 // Prevent stacking of mounts
5089 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5091 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5092 if (unitTarget->GetAreaId() == 3428)
5093 unitTarget->CastSpell(unitTarget, 25863, false);
5094 else
5095 unitTarget->CastSpell(unitTarget, 26655, false);
5096 return;
5098 // Mirren's Drinking Hat
5099 case 29830:
5101 uint32 item = 0;
5102 switch ( urand(1, 6) )
5104 case 1:
5105 case 2:
5106 case 3:
5107 item = 23584; break; // Loch Modan Lager
5108 case 4:
5109 case 5:
5110 item = 23585; break; // Stouthammer Lite
5111 case 6:
5112 item = 23586; break; // Aerie Peak Pale Ale
5114 if (item)
5115 DoCreateItem(effIndex,item);
5116 break;
5118 // Improved Sprint
5119 case 30918:
5121 if(!unitTarget)
5122 return;
5123 // Removes snares and roots.
5124 unitTarget->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,30918,true);
5125 break;
5127 // Flame Crash
5128 case 41126:
5130 if(!unitTarget)
5131 return;
5133 unitTarget->CastSpell(unitTarget, 41131, true);
5134 break;
5136 // Force Cast - Portal Effect: Sunwell Isle
5137 case 44876:
5139 if(!unitTarget)
5140 return;
5142 unitTarget->CastSpell(unitTarget, 44870, true);
5143 break;
5145 // Goblin Weather Machine
5146 case 46203:
5148 if(!unitTarget)
5149 return;
5151 uint32 spellId = 0;
5152 switch(rand() % 4)
5154 case 0: spellId = 46740; break;
5155 case 1: spellId = 46739; break;
5156 case 2: spellId = 46738; break;
5157 case 3: spellId = 46736; break;
5159 unitTarget->CastSpell(unitTarget, spellId, true);
5160 break;
5162 //5,000 Gold
5163 case 46642:
5165 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5166 return;
5168 ((Player*)unitTarget)->ModifyMoney(50000000);
5170 break;
5172 // Surge Needle Teleporter
5173 case 47097:
5175 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5176 return;
5178 if (unitTarget->GetAreaId() == 4156)
5179 unitTarget->CastSpell(unitTarget, 47324, true);
5180 else if (unitTarget->GetAreaId() == 4157)
5181 unitTarget->CastSpell(unitTarget, 47325, true);
5183 break;
5185 // High Executor's Branding Iron
5186 case 48603:
5187 // Torture the Torturer: High Executor's Branding Iron Impact
5188 unitTarget->CastSpell(unitTarget, 48614, true);
5189 return;
5190 // Emblazon Runeblade
5191 case 51770:
5193 if(!m_originalCaster)
5194 return;
5196 m_originalCaster->CastSpell(m_originalCaster, damage, false);
5197 break;
5199 // Death Gate
5200 case 52751:
5202 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5203 return;
5204 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5205 unitTarget->CastSpell(unitTarget, damage, false);
5206 break;
5208 // Winged Steed of the Ebon Blade
5209 case 54729:
5211 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5212 return;
5214 // Prevent stacking of mounts
5215 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5217 // Triggered spell id dependent of riding skill
5218 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5220 if (skillval >= 300)
5221 unitTarget->CastSpell(unitTarget, 54727, true);
5222 else
5223 unitTarget->CastSpell(unitTarget, 54726, true);
5225 return;
5227 // Demonic Empowerment (succubus Vanish effect)
5228 case 54436:
5230 if(!unitTarget)
5231 return;
5233 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5234 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5235 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
5236 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
5237 return;
5239 case 55693: // Remove Collapsing Cave Aura
5240 if(!unitTarget)
5241 return;
5242 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex));
5243 break;
5244 case 58418: // Portal to Orgrimmar
5245 case 58420: // Portal to Stormwind
5247 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
5248 return;
5250 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
5251 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
5253 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5254 unitTarget->CastSpell(unitTarget, spellID, true);
5256 return;
5258 case 59317: // Teleporting
5259 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5260 return;
5262 // return from top
5263 if (((Player*)unitTarget)->GetAreaId() == 4637)
5264 unitTarget->CastSpell(unitTarget, 59316, true);
5265 // teleport atop
5266 else
5267 unitTarget->CastSpell(unitTarget, 59314, true);
5269 return;
5270 // random spell learn instead placeholder
5271 case 60893: // Northrend Alchemy Research
5272 case 61177: // Northrend Inscription Research
5273 case 61288: // Minor Inscription Research
5274 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5275 case 64323: // Book of Glyph Mastery
5277 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5278 return;
5280 // learn random explicit discovery recipe (if any)
5281 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5282 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5283 return;
5286 break;
5288 case SPELLFAMILY_WARLOCK:
5290 switch(m_spellInfo->Id)
5292 // Healthstone creating spells
5293 case 6201:
5294 case 6202:
5295 case 5699:
5296 case 11729:
5297 case 11730:
5298 case 27230:
5299 case 47871:
5300 case 47878:
5302 if(!unitTarget)
5303 return;
5304 uint32 itemtype;
5305 uint32 rank = 0;
5306 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5307 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5309 if((*i)->GetId() == 18692)
5311 rank = 1;
5312 break;
5314 else if((*i)->GetId() == 18693)
5316 rank = 2;
5317 break;
5321 static uint32 const itypes[8][3] = {
5322 { 5512, 19004, 19005}, // Minor Healthstone
5323 { 5511, 19006, 19007}, // Lesser Healthstone
5324 { 5509, 19008, 19009}, // Healthstone
5325 { 5510, 19010, 19011}, // Greater Healthstone
5326 { 9421, 19012, 19013}, // Major Healthstone
5327 {22103, 22104, 22105}, // Master Healthstone
5328 {36889, 36890, 36891}, // Demonic Healthstone
5329 {36892, 36893, 36894} // Fel Healthstone
5332 switch(m_spellInfo->Id)
5334 case 6201:
5335 itemtype=itypes[0][rank];break; // Minor Healthstone
5336 case 6202:
5337 itemtype=itypes[1][rank];break; // Lesser Healthstone
5338 case 5699:
5339 itemtype=itypes[2][rank];break; // Healthstone
5340 case 11729:
5341 itemtype=itypes[3][rank];break; // Greater Healthstone
5342 case 11730:
5343 itemtype=itypes[4][rank];break; // Major Healthstone
5344 case 27230:
5345 itemtype=itypes[5][rank];break; // Master Healthstone
5346 case 47871:
5347 itemtype=itypes[6][rank];break; // Demonic Healthstone
5348 case 47878:
5349 itemtype=itypes[7][rank];break; // Fel Healthstone
5350 default:
5351 return;
5353 DoCreateItem( effIndex, itemtype );
5354 return;
5356 // Demonic Empowerment
5357 case 47193:
5359 if(!unitTarget)
5360 return;
5361 uint32 entry = unitTarget->GetEntry();
5362 uint32 spellID;
5363 switch(entry)
5365 case 416: spellID = 54444; break; //imp
5366 case 417: spellID = 54509; break; //fellhunter
5367 case 1860: spellID = 54443; break; //void
5368 case 1863: spellID = 54435; break; //succubus
5369 case 17252: spellID = 54508; break; //fellguard
5370 default:
5371 return;
5373 unitTarget->CastSpell(unitTarget,spellID,true);
5374 return;
5376 // Everlasting Affliction
5377 case 47422:
5379 // Need refresh caster corruption auras on target
5380 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5381 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5383 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5384 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5385 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5386 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5387 (*itr).second->RefreshAura();
5389 return;
5391 // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5392 case 63521:
5394 // Divine Plea, refresh on target (3 aura slots)
5395 if (Aura* aura = unitTarget->GetAura(54428,0))
5396 aura->RefreshAura();
5397 return;
5400 break;
5402 case SPELLFAMILY_PRIEST:
5404 switch(m_spellInfo->Id)
5406 // Pain and Suffering
5407 case 47948:
5409 if (!unitTarget)
5410 return;
5411 // Refresh Shadow Word: Pain on target
5412 Unit::AuraMap& auras = unitTarget->GetAuras();
5413 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5415 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5416 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5417 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5418 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5420 (*itr).second->RefreshAura();
5421 return;
5424 return;
5426 default:
5427 break;
5429 break;
5431 case SPELLFAMILY_HUNTER:
5433 switch(m_spellInfo->Id)
5435 // Chimera Shot
5436 case 53209:
5438 if(!unitTarget)
5439 return;
5440 uint32 spellId = 0;
5441 int32 basePoint = 0;
5442 Unit* target = unitTarget;
5443 Unit::AuraMap& Auras = unitTarget->GetAuras();
5444 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5446 Aura *aura = (*i).second;
5447 if (aura->GetCasterGUID() != m_caster->GetGUID())
5448 continue;
5449 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5450 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5451 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5452 continue;
5453 // Refresh aura duration
5454 aura->RefreshAura();
5456 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5457 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == 0)
5459 // m_amount already include RAP bonus
5460 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5461 spellId = 53353; // Chimera Shot - Serpent
5463 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5464 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == 0)
5466 uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
5467 if (!target_max_mana)
5468 continue;
5470 // ignore non positive values (can be result apply spellmods to aura damage
5471 uint32 pdamage = aura->GetModifier()->m_amount > 0 ? aura->GetModifier()->m_amount : 0;
5473 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5474 uint32 maxmana = m_caster->GetMaxPower(POWER_MANA) * pdamage * 2 / 100;
5476 pdamage = target_max_mana * pdamage / 100;
5477 if (pdamage > maxmana)
5478 pdamage = maxmana;
5480 pdamage *= 4; // total aura damage
5481 basePoint = pdamage * 60 / 100;
5482 spellId = 53358; // Chimera Shot - Viper
5483 target = m_caster;
5485 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5486 if (familyFlag & UI64LIT(0x0000000000008000))
5487 spellId = 53359; // Chimera Shot - Scorpid
5488 // ?? nothing say in spell desc (possibly need addition check)
5489 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5490 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5492 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5495 if (spellId)
5496 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5497 return;
5499 case 53412: // Invigoration (pet triggered script, master targeted)
5501 if (!unitTarget)
5502 return;
5504 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5505 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5507 // Invigoration (master talent)
5508 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5510 if (roll_chance_i((*i)->GetModifier()->m_amount))
5512 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5513 break;
5517 return;
5519 // Master's Call
5520 case 53271:
5522 if (!unitTarget)
5523 return;
5525 // script effect have in value, but this outdated removed part
5526 unitTarget->CastSpell(unitTarget, 62305, true);
5527 return;
5529 default:
5530 break;
5532 break;
5534 case SPELLFAMILY_PALADIN:
5536 // Judgement (seal trigger)
5537 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5539 if(!unitTarget || !unitTarget->isAlive())
5540 return;
5541 uint32 spellId1 = 0;
5542 uint32 spellId2 = 0;
5544 // Judgement self add switch
5545 switch (m_spellInfo->Id)
5547 case 53407: spellId1 = 20184; break; // Judgement of Justice
5548 case 20271: // Judgement of Light
5549 case 57774: spellId1 = 20185; break; // Judgement of Light
5550 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5551 default:
5552 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
5553 return;
5555 // offensive seals have aura dummy in 2 effect
5556 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5557 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5559 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
5560 if ((*itr)->GetEffIndex() != 2 || !IsSealSpell((*itr)->GetSpellProto()))
5561 continue;
5562 spellId2 = (*itr)->GetModifier()->m_amount;
5563 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5564 if (!judge)
5565 continue;
5566 break;
5568 // if there were no offensive seals than there is seal with proc trigger aura
5569 if (!spellId2)
5571 Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5572 for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
5574 if ((*itr)->GetEffIndex() != 0 || !IsSealSpell((*itr)->GetSpellProto()))
5575 continue;
5576 spellId2 = 54158;
5577 break;
5580 if (spellId1)
5581 m_caster->CastSpell(unitTarget, spellId1, true);
5582 if (spellId2)
5583 m_caster->CastSpell(unitTarget, spellId2, true);
5584 return;
5587 case SPELLFAMILY_POTION:
5589 switch(m_spellInfo->Id)
5591 // Dreaming Glory
5592 case 28698:
5594 if(!unitTarget)
5595 return;
5596 unitTarget->CastSpell(unitTarget, 28694, true);
5597 break;
5599 // Netherbloom
5600 case 28702:
5602 if(!unitTarget)
5603 return;
5604 // 25% chance of casting a random buff
5605 if(roll_chance_i(75))
5606 return;
5608 // triggered spells are 28703 to 28707
5609 // Note: some sources say, that there was the possibility of
5610 // receiving a debuff. However, this seems to be removed by a patch.
5611 const uint32 spellid = 28703;
5613 // don't overwrite an existing aura
5614 for(uint8 i = 0; i < 5; ++i)
5615 if(unitTarget->HasAura(spellid + i, 0))
5616 return;
5617 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5618 break;
5621 // Nightmare Vine
5622 case 28720:
5624 if(!unitTarget)
5625 return;
5626 // 25% chance of casting Nightmare Pollen
5627 if(roll_chance_i(75))
5628 return;
5629 unitTarget->CastSpell(unitTarget, 28721, true);
5630 break;
5633 break;
5635 case SPELLFAMILY_DEATHKNIGHT:
5637 switch(m_spellInfo->Id)
5639 // Pestilence
5640 case 50842:
5642 if(!unitTarget)
5643 return;
5645 Unit* mainTarget = m_targets.getUnitTarget();
5646 if(!mainTarget)
5647 return;
5649 // do only refresh diseases on main target if caster has Glyph of Disease
5650 if(mainTarget == unitTarget && !m_caster->HasAura(63334))
5651 return;
5653 // Blood Plague
5654 if(mainTarget->HasAura(55078))
5655 m_caster->CastSpell(unitTarget, 55078, true);
5657 // Frost Fever
5658 if(mainTarget->HasAura(55095))
5659 m_caster->CastSpell(unitTarget, 55095, true);
5661 break;
5664 break;
5668 // normal DB scripted effect
5669 if(!unitTarget)
5670 return;
5672 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5673 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5676 void Spell::EffectSanctuary(uint32 /*i*/)
5678 if(!unitTarget)
5679 return;
5680 //unitTarget->CombatStop();
5682 unitTarget->CombatStop();
5683 unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
5684 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5685 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5687 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5691 void Spell::EffectAddComboPoints(uint32 /*i*/)
5693 if(!unitTarget)
5694 return;
5696 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5697 return;
5699 if(damage <= 0)
5700 return;
5702 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5705 void Spell::EffectDuel(uint32 i)
5707 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5708 return;
5710 Player *caster = (Player*)m_caster;
5711 Player *target = (Player*)unitTarget;
5713 // caster or target already have requested duel
5714 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5715 return;
5717 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5718 // Don't have to check the target's map since you cannot challenge someone across maps
5719 uint32 mapid = caster->GetMapId();
5720 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5722 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5723 return;
5726 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5727 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5729 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5730 return;
5733 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5734 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5736 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5737 return;
5740 //CREATE DUEL FLAG OBJECT
5741 GameObject* pGameObj = new GameObject;
5743 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5745 Map *map = m_caster->GetMap();
5746 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5747 map, m_caster->GetPhaseMask(),
5748 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5749 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5750 m_caster->GetPositionZ(),
5751 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5753 delete pGameObj;
5754 return;
5757 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5758 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5759 int32 duration = GetSpellDuration(m_spellInfo);
5760 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5761 pGameObj->SetSpellId(m_spellInfo->Id);
5763 m_caster->AddGameObject(pGameObj);
5764 map->Add(pGameObj);
5765 //END
5767 // Send request
5768 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
5769 data << uint64(pGameObj->GetGUID());
5770 data << uint64(caster->GetGUID());
5771 caster->GetSession()->SendPacket(&data);
5772 target->GetSession()->SendPacket(&data);
5774 // create duel-info
5775 DuelInfo *duel = new DuelInfo;
5776 duel->initiator = caster;
5777 duel->opponent = target;
5778 duel->startTime = 0;
5779 duel->startTimer = 0;
5780 caster->duel = duel;
5782 DuelInfo *duel2 = new DuelInfo;
5783 duel2->initiator = caster;
5784 duel2->opponent = caster;
5785 duel2->startTime = 0;
5786 duel2->startTimer = 0;
5787 target->duel = duel2;
5789 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5790 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5793 void Spell::EffectStuck(uint32 /*i*/)
5795 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5796 return;
5798 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5799 return;
5801 Player* pTarget = (Player*)unitTarget;
5803 sLog.outDebug("Spell Effect: Stuck");
5804 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());
5806 if(pTarget->isInFlight())
5807 return;
5809 // homebind location is loaded always
5810 pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
5812 // Stuck spell trigger Hearthstone cooldown
5813 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5814 if(!spellInfo)
5815 return;
5816 Spell spell(pTarget, spellInfo, true, 0);
5817 spell.SendSpellCooldown();
5820 void Spell::EffectSummonPlayer(uint32 /*i*/)
5822 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5823 return;
5825 // Evil Twin (ignore player summon, but hide this for summoner)
5826 if(unitTarget->GetDummyAura(23445))
5827 return;
5829 float x, y, z;
5830 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
5832 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5834 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5835 data << uint64(m_caster->GetGUID()); // summoner guid
5836 data << uint32(m_caster->GetZoneId()); // summoner zone
5837 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5838 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5841 static ScriptInfo generateActivateCommand()
5843 ScriptInfo si;
5844 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5845 return si;
5848 void Spell::EffectActivateObject(uint32 effect_idx)
5850 if(!gameObjTarget)
5851 return;
5853 static ScriptInfo activateCommand = generateActivateCommand();
5855 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5857 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5860 void Spell::EffectApplyGlyph(uint32 i)
5862 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5863 return;
5865 Player *player = (Player*)m_caster;
5867 // apply new one
5868 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5870 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5872 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5874 if(gp->TypeFlags != gs->TypeFlags)
5876 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5877 return; // glyph slot mismatch
5881 // remove old glyph
5882 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5884 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5886 player->RemoveAurasDueToSpell(old_gp->SpellId);
5887 player->SetGlyph(m_glyphIndex, 0);
5891 player->CastSpell(m_caster, gp->SpellId, true);
5892 player->SetGlyph(m_glyphIndex, glyph);
5893 player->SendTalentsInfoData(false);
5898 void Spell::EffectSummonTotem(uint32 i, uint8 slot)
5900 slot = slot ? (slot - 1): 255;
5902 if(slot < MAX_TOTEM)
5904 uint64 guid = m_caster->m_TotemSlot[slot];
5905 if(guid != 0)
5907 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5908 if(OldTotem && OldTotem->isTotem())
5909 ((Totem*)OldTotem)->UnSummon();
5913 uint32 team = 0;
5914 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5915 team = ((Player*)m_caster)->GetTeam();
5917 Totem* pTotem = new Totem;
5919 if(!pTotem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5920 m_spellInfo->EffectMiscValue[i], team ))
5922 delete pTotem;
5923 return;
5926 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5928 float x, y, z;
5929 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
5931 // totem must be at same Z in case swimming caster and etc.
5932 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5933 z = m_caster->GetPositionZ();
5935 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5937 if(slot < MAX_TOTEM)
5938 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5940 pTotem->SetOwner(m_caster->GetGUID());
5941 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5943 int32 duration=GetSpellDuration(m_spellInfo);
5944 if(Player* modOwner = m_caster->GetSpellModOwner())
5945 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
5946 pTotem->SetDuration(duration);
5948 if (damage) // if not spell info, DB values used
5950 pTotem->SetMaxHealth(damage);
5951 pTotem->SetHealth(damage);
5954 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5956 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5957 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
5959 if(m_caster->IsPvP())
5960 pTotem->SetPvP(true);
5962 pTotem->Summon(m_caster);
5964 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5966 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
5967 data << uint8(slot);
5968 data << uint64(pTotem->GetGUID());
5969 data << uint32(duration);
5970 data << uint32(m_spellInfo->Id);
5971 ((Player*)m_caster)->SendDirectMessage(&data);
5975 void Spell::EffectEnchantHeldItem(uint32 i)
5977 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5978 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5979 return;
5981 Player* item_owner = (Player*)unitTarget;
5982 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5984 if(!item )
5985 return;
5987 // must be equipped
5988 if(!item ->IsEquipped())
5989 return;
5991 if (m_spellInfo->EffectMiscValue[i])
5993 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5994 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5995 if(!duration)
5996 duration = m_currentBasePoints[i]+1; //Base points after ..
5997 if(!duration)
5998 duration = 10; //10 seconds for enchants which don't have listed duration
6000 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6001 if(!pEnchant)
6002 return;
6004 // Always go to temp enchantment slot
6005 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
6007 // Enchantment will not be applied if a different one already exists
6008 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
6009 return;
6011 // Apply the temporary enchantment
6012 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
6013 item_owner->ApplyEnchantment(item, slot, true);
6017 void Spell::EffectDisEnchant(uint32 /*i*/)
6019 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6020 return;
6022 Player* p_caster = (Player*)m_caster;
6023 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
6024 return;
6026 p_caster->UpdateCraftSkill(m_spellInfo->Id);
6028 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
6030 // item will be removed at disenchanting end
6033 void Spell::EffectInebriate(uint32 /*i*/)
6035 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6036 return;
6038 Player *player = (Player*)unitTarget;
6039 uint16 currentDrunk = player->GetDrunkValue();
6040 uint16 drunkMod = damage * 256;
6041 if (currentDrunk + drunkMod > 0xFFFF)
6042 currentDrunk = 0xFFFF;
6043 else
6044 currentDrunk += drunkMod;
6045 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
6048 void Spell::EffectFeedPet(uint32 i)
6050 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6051 return;
6053 Player *_player = (Player*)m_caster;
6055 Item* foodItem = m_targets.getItemTarget();
6056 if(!foodItem)
6057 return;
6059 Pet *pet = _player->GetPet();
6060 if(!pet)
6061 return;
6063 if(!pet->isAlive())
6064 return;
6066 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
6067 if(benefit <= 0)
6068 return;
6070 uint32 count = 1;
6071 _player->DestroyItemCount(foodItem,count,true);
6072 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6074 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[i], &benefit, NULL, NULL, true);
6077 void Spell::EffectDismissPet(uint32 /*i*/)
6079 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6080 return;
6082 Pet* pet = m_caster->GetPet();
6084 // not let dismiss dead pet
6085 if(!pet||!pet->isAlive())
6086 return;
6088 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
6091 void Spell::EffectSummonObject(uint32 i)
6093 uint32 go_id = m_spellInfo->EffectMiscValue[i];
6095 uint8 slot = 0;
6096 switch(m_spellInfo->Effect[i])
6098 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
6099 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
6100 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
6101 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
6102 default: return;
6105 if(uint64 guid = m_caster->m_ObjectSlot[slot])
6107 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
6108 obj->SetLootState(GO_JUST_DEACTIVATED);
6109 m_caster->m_ObjectSlot[slot] = 0;
6112 GameObject* pGameObj = new GameObject;
6114 float x, y, z;
6115 // If dest location if present
6116 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6118 x = m_targets.m_destX;
6119 y = m_targets.m_destY;
6120 z = m_targets.m_destZ;
6122 // Summon in random point all other units if location present
6123 else
6124 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
6126 Map *map = m_caster->GetMap();
6127 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
6128 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6130 delete pGameObj;
6131 return;
6134 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
6135 int32 duration = GetSpellDuration(m_spellInfo);
6136 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6137 pGameObj->SetSpellId(m_spellInfo->Id);
6138 m_caster->AddGameObject(pGameObj);
6140 map->Add(pGameObj);
6142 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
6145 void Spell::EffectResurrect(uint32 /*effIndex*/)
6147 if(!unitTarget)
6148 return;
6149 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6150 return;
6152 if(unitTarget->isAlive())
6153 return;
6154 if(!unitTarget->IsInWorld())
6155 return;
6157 switch (m_spellInfo->Id)
6159 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6160 case 8342:
6161 if (roll_chance_i(67))
6163 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
6164 return;
6166 break;
6167 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6168 case 22999:
6169 if (roll_chance_i(50))
6171 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
6172 return;
6174 break;
6175 default:
6176 break;
6179 Player* pTarget = ((Player*)unitTarget);
6181 if(pTarget->isRessurectRequested()) // already have one active request
6182 return;
6184 uint32 health = pTarget->GetMaxHealth() * damage / 100;
6185 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
6187 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
6188 SendResurrectRequest(pTarget);
6191 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
6193 if(!unitTarget || !unitTarget->isAlive())
6194 return;
6196 if( unitTarget->m_extraAttacks )
6197 return;
6199 unitTarget->m_extraAttacks = damage;
6202 void Spell::EffectParry(uint32 /*i*/)
6204 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6205 ((Player*)unitTarget)->SetCanParry(true);
6208 void Spell::EffectBlock(uint32 /*i*/)
6210 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6211 ((Player*)unitTarget)->SetCanBlock(true);
6214 void Spell::EffectLeapForward(uint32 i)
6216 if(unitTarget->isInFlight())
6217 return;
6219 if( m_spellInfo->rangeIndex == 1) //self range
6221 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6223 // before caster
6224 float fx, fy, fz;
6225 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6226 float ox, oy, oz;
6227 unitTarget->GetPosition(ox, oy, oz);
6229 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6230 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
6232 fx = fx2;
6233 fy = fy2;
6234 fz = fz2;
6235 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6238 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6242 void Spell::EffectLeapBack(uint32 i)
6244 if(unitTarget->isInFlight())
6245 return;
6247 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6250 void Spell::EffectReputation(uint32 i)
6252 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6253 return;
6255 Player *_player = (Player*)unitTarget;
6257 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
6259 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
6261 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6263 if(!factionEntry)
6264 return;
6266 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6269 void Spell::EffectQuestComplete(uint32 i)
6271 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6272 return;
6274 Player *_player = (Player*)m_caster;
6276 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
6277 _player->AreaExploredOrEventHappens(quest_id);
6280 void Spell::EffectSelfResurrect(uint32 i)
6282 if(!unitTarget || unitTarget->isAlive())
6283 return;
6284 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6285 return;
6286 if(!unitTarget->IsInWorld())
6287 return;
6289 uint32 health = 0;
6290 uint32 mana = 0;
6292 // flat case
6293 if(damage < 0)
6295 health = uint32(-damage);
6296 mana = m_spellInfo->EffectMiscValue[i];
6298 // percent case
6299 else
6301 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6302 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6303 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6306 Player *plr = ((Player*)unitTarget);
6307 plr->ResurrectPlayer(0.0f);
6309 plr->SetHealth( health );
6310 plr->SetPower(POWER_MANA, mana );
6311 plr->SetPower(POWER_RAGE, 0 );
6312 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6314 plr->SpawnCorpseBones();
6317 void Spell::EffectSkinning(uint32 /*i*/)
6319 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6320 return;
6321 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6322 return;
6324 Creature* creature = (Creature*) unitTarget;
6325 int32 targetLevel = creature->getLevel();
6327 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6329 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6330 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6332 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6334 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6336 // Double chances for elites
6337 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6340 void Spell::EffectCharge(uint32 /*i*/)
6342 if (!unitTarget)
6343 return;
6345 //TODO: research more ContactPoint/attack distance.
6346 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6347 float x, y, z;
6348 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6350 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6351 ((Creature *)unitTarget)->StopMoving();
6353 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6354 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6356 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6357 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6359 // not all charge effects used in negative spells
6360 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6361 m_caster->Attack(unitTarget,true);
6364 void Spell::EffectCharge2(uint32 /*i*/)
6366 float x, y, z;
6367 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6369 x = m_targets.m_destX;
6370 y = m_targets.m_destY;
6371 z = m_targets.m_destZ;
6373 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6374 ((Creature *)unitTarget)->StopMoving();
6376 else if (unitTarget && unitTarget != m_caster)
6377 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6378 else
6379 return;
6381 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6382 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6384 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6385 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6387 // not all charge effects used in negative spells
6388 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6389 m_caster->Attack(unitTarget,true);
6392 void Spell::EffectSummonCritter(uint32 i, uint32 forceFaction)
6394 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6395 return;
6396 Player* player = (Player*)m_caster;
6398 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
6399 if(!pet_entry)
6400 return;
6402 Pet* old_critter = player->GetMiniPet();
6404 // for same pet just despawn
6405 if(old_critter && old_critter->GetEntry() == pet_entry)
6407 player->RemoveMiniPet();
6408 return;
6411 // despawn old pet before summon new
6412 if(old_critter)
6413 player->RemoveMiniPet();
6415 // summon new pet
6416 Pet* critter = new Pet(MINI_PET);
6418 Map *map = m_caster->GetMap();
6419 uint32 pet_number = sObjectMgr.GeneratePetNumber();
6420 if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6421 pet_entry, pet_number))
6423 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6424 delete critter;
6425 return;
6428 float x, y, z;
6429 // If dest location if present
6430 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6432 x = m_targets.m_destX;
6433 y = m_targets.m_destY;
6434 z = m_targets.m_destZ;
6436 // Summon if dest location not present near caster
6437 else
6438 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6440 critter->Relocate(x, y, z, m_caster->GetOrientation());
6442 if(!critter->IsPositionValid())
6444 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6445 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6446 delete critter;
6447 return;
6450 critter->SetOwnerGUID(m_caster->GetGUID());
6451 critter->SetCreatorGUID(m_caster->GetGUID());
6453 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6454 critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
6455 critter->AIM_Initialize();
6456 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6457 //critter->InitLevelupSpellsForLevel(); // none?
6458 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6459 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6460 // some mini-pets have quests
6462 // set timer for unsummon
6463 int32 duration = GetSpellDuration(m_spellInfo);
6464 if(duration > 0)
6465 critter->SetDuration(duration);
6467 std::string name = player->GetName();
6468 name.append(petTypeSuffix[critter->getPetType()]);
6469 critter->SetName( name );
6470 player->SetMiniPet(critter);
6472 map->Add((Creature*)critter);
6475 void Spell::EffectKnockBack(uint32 i)
6477 if(!unitTarget)
6478 return;
6480 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6483 void Spell::EffectSendTaxi(uint32 i)
6485 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6486 return;
6488 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id);
6491 void Spell::EffectPlayerPull(uint32 i)
6493 if(!unitTarget)
6494 return;
6496 float dist = unitTarget->GetDistance2d(m_caster);
6497 if (damage && dist > damage)
6498 dist = damage;
6500 unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[i])/10);
6503 void Spell::EffectDispelMechanic(uint32 i)
6505 if(!unitTarget)
6506 return;
6508 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6510 Unit::AuraMap& Auras = unitTarget->GetAuras();
6511 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6513 next = iter;
6514 ++next;
6515 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6516 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6518 unitTarget->RemoveAurasDueToSpell(spell->Id);
6519 if(Auras.empty())
6520 break;
6521 else
6522 next = Auras.begin();
6525 return;
6528 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6530 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6531 return;
6532 Player *_player = (Player*)m_caster;
6533 Pet *pet = _player->GetPet();
6534 if(!pet)
6535 return;
6536 if(pet->isAlive())
6537 return;
6538 if(damage < 0)
6539 return;
6540 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6541 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6542 pet->setDeathState( ALIVE );
6543 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6544 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6546 pet->AIM_Initialize();
6548 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6549 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6552 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6554 int32 mana = 0;
6555 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6557 if(!m_caster->m_TotemSlot[slot])
6558 continue;
6560 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6561 if(totem && totem->isTotem())
6563 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6564 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6565 if(spellInfo)
6567 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6568 mana += manacost * damage / 100;
6570 ((Totem*)totem)->UnSummon();
6574 if (mana)
6575 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
6578 void Spell::EffectDurabilityDamage(uint32 i)
6580 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6581 return;
6583 int32 slot = m_spellInfo->EffectMiscValue[i];
6585 // FIXME: some spells effects have value -1/-2
6586 // Possibly its mean -1 all player equipped items and -2 all items
6587 if(slot < 0)
6589 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
6590 return;
6593 // invalid slot value
6594 if(slot >= INVENTORY_SLOT_BAG_END)
6595 return;
6597 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6598 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
6601 void Spell::EffectDurabilityDamagePCT(uint32 i)
6603 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6604 return;
6606 int32 slot = m_spellInfo->EffectMiscValue[i];
6608 // FIXME: some spells effects have value -1/-2
6609 // Possibly its mean -1 all player equipped items and -2 all items
6610 if(slot < 0)
6612 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
6613 return;
6616 // invalid slot value
6617 if(slot >= INVENTORY_SLOT_BAG_END)
6618 return;
6620 if(damage <= 0)
6621 return;
6623 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6624 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
6627 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6629 if(!unitTarget)
6630 return;
6632 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6635 void Spell::EffectTransmitted(uint32 effIndex)
6637 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6639 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
6641 if (!goinfo)
6643 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6644 return;
6647 float fx, fy, fz;
6649 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6651 fx = m_targets.m_destX;
6652 fy = m_targets.m_destY;
6653 fz = m_targets.m_destZ;
6655 //FIXME: this can be better check for most objects but still hack
6656 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6658 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6659 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6661 else
6663 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6664 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6665 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6667 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6670 Map *cMap = m_caster->GetMap();
6672 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6674 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6675 { // but this is not proper, we really need to ignore not materialized objects
6676 SendCastResult(SPELL_FAILED_NOT_HERE);
6677 SendChannelUpdate(0);
6678 return;
6681 // replace by water level in this case
6682 fz = cMap->GetWaterLevel(fx, fy);
6684 // if gameobject is summoning object, it should be spawned right on caster's position
6685 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6687 m_caster->GetPosition(fx, fy, fz);
6690 GameObject* pGameObj = new GameObject;
6692 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6693 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6695 delete pGameObj;
6696 return;
6699 int32 duration = GetSpellDuration(m_spellInfo);
6701 switch(goinfo->type)
6703 case GAMEOBJECT_TYPE_FISHINGNODE:
6705 m_caster->SetChannelObjectGUID(pGameObj->GetGUID());
6706 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6708 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6709 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6710 int32 lastSec = 0;
6711 switch(urand(0, 3))
6713 case 0: lastSec = 3; break;
6714 case 1: lastSec = 7; break;
6715 case 2: lastSec = 13; break;
6716 case 3: lastSec = 17; break;
6719 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6720 break;
6722 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6724 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6726 pGameObj->AddUniqueUse((Player*)m_caster);
6727 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6729 break;
6731 case GAMEOBJECT_TYPE_FISHINGHOLE:
6732 case GAMEOBJECT_TYPE_CHEST:
6733 default:
6734 break;
6737 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6739 pGameObj->SetOwnerGUID(m_caster->GetGUID());
6741 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6742 pGameObj->SetSpellId(m_spellInfo->Id);
6744 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6745 //m_caster->AddGameObject(pGameObj);
6746 //m_ObjToDel.push_back(pGameObj);
6748 cMap->Add(pGameObj);
6750 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
6752 GameObject* linkedGO = new GameObject;
6753 if(linkedGO->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6754 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6756 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6757 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6758 linkedGO->SetSpellId(m_spellInfo->Id);
6759 linkedGO->SetOwnerGUID(m_caster->GetGUID());
6761 linkedGO->GetMap()->Add(linkedGO);
6763 else
6765 delete linkedGO;
6766 linkedGO = NULL;
6767 return;
6772 void Spell::EffectProspecting(uint32 /*i*/)
6774 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6775 return;
6777 Player* p_caster = (Player*)m_caster;
6778 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6779 return;
6781 if(itemTarget->GetCount() < 5)
6782 return;
6784 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6786 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6787 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6788 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6791 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6794 void Spell::EffectMilling(uint32 /*i*/)
6796 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6797 return;
6799 Player* p_caster = (Player*)m_caster;
6800 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6801 return;
6803 if(itemTarget->GetCount() < 5)
6804 return;
6806 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6808 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6809 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6810 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6813 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6816 void Spell::EffectSkill(uint32 /*i*/)
6818 sLog.outDebug("WORLD: SkillEFFECT");
6821 void Spell::EffectSpiritHeal(uint32 /*i*/)
6823 // TODO player can't see the heal-animation - he should respawn some ticks later
6824 if (!unitTarget || unitTarget->isAlive())
6825 return;
6826 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6827 return;
6828 if (!unitTarget->IsInWorld())
6829 return;
6830 if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584))
6831 return;
6833 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6834 ((Player*)unitTarget)->SpawnCorpseBones();
6837 // remove insignia spell effect
6838 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6840 sLog.outDebug("Effect: SkinPlayerCorpse");
6841 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6842 return;
6844 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6847 void Spell::EffectStealBeneficialBuff(uint32 i)
6849 sLog.outDebug("Effect: StealBeneficialBuff");
6851 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6852 return;
6854 std::vector <Aura *> steal_list;
6855 // Create dispel mask by dispel type
6856 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6857 Unit::AuraMap const& auras = unitTarget->GetAuras();
6858 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6860 Aura *aur = (*itr).second;
6861 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6863 // Need check for passive? this
6864 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6865 steal_list.push_back(aur);
6868 // Ok if exist some buffs for dispel try dispel it
6869 if (!steal_list.empty())
6871 std::list < std::pair<uint32,uint64> > success_list;
6872 int32 list_size = steal_list.size();
6873 // Dispell N = damage buffs (or while exist buffs for dispel)
6874 for (int32 count=0; count < damage && list_size > 0; ++count)
6876 // Random select buff for dispel
6877 Aura *aur = steal_list[urand(0, list_size-1)];
6878 // Not use chance for steal
6879 // TODO possible need do it
6880 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6882 // Remove buff from list for prevent doubles
6883 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6885 Aura *stealed = *j;
6886 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6888 j = steal_list.erase(j);
6889 --list_size;
6891 else
6892 ++j;
6895 // Really try steal and send log
6896 if (!success_list.empty())
6898 int32 count = success_list.size();
6899 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6900 data.append(unitTarget->GetPackGUID()); // Victim GUID
6901 data.append(m_caster->GetPackGUID()); // Caster GUID
6902 data << uint32(m_spellInfo->Id); // Dispell spell id
6903 data << uint8(0); // not used
6904 data << uint32(count); // count
6905 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6907 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6908 data << uint32(spellInfo->Id); // Spell Id
6909 data << uint8(0); // 0 - steals !=0 transfers
6910 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6912 m_caster->SendMessageToSet(&data, true);
6917 void Spell::EffectKillCreditPersonal(uint32 i)
6919 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6920 return;
6922 ((Player*)unitTarget)->KilledMonsterCredit(m_spellInfo->EffectMiscValue[i], 0);
6925 void Spell::EffectKillCredit(uint32 i)
6927 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6928 return;
6930 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6933 void Spell::EffectQuestFail(uint32 i)
6935 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6936 return;
6938 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6941 void Spell::EffectActivateRune(uint32 eff_idx)
6943 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6944 return;
6946 Player *plr = (Player*)m_caster;
6948 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6949 return;
6951 for(uint32 j = 0; j < MAX_RUNES; ++j)
6953 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
6955 plr->SetRuneCooldown(j, 0);
6960 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6962 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6963 ((Player*)unitTarget)->SetCanTitanGrip(true);
6966 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6968 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6969 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6970 return;
6972 unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
6975 void Spell::EffectPlayMusic(uint32 i)
6977 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6978 return;
6980 uint32 soundid = m_spellInfo->EffectMiscValue[i];
6982 if (!sSoundEntriesStore.LookupEntry(soundid))
6984 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
6985 return;
6988 WorldPacket data(SMSG_PLAY_MUSIC, 4);
6989 data << uint32(soundid);
6990 ((Player*)unitTarget)->GetSession()->SendPacket(&data);