Merge branch 'master' into 303
[getmangos.git] / src / game / SpellEffects.cpp
blob09236f84ec7bfe01764d95a6d6849a6e6d27b1f3
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "UpdateMask.h"
27 #include "World.h"
28 #include "ObjectMgr.h"
29 #include "SpellMgr.h"
30 #include "Player.h"
31 #include "SkillExtraItems.h"
32 #include "Unit.h"
33 #include "CreatureAI.h"
34 #include "Spell.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
37 #include "Group.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
42 #include "Pet.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
45 #include "Creature.h"
46 #include "Totem.h"
47 #include "CreatureAI.h"
48 #include "BattleGround.h"
49 #include "BattleGroundEY.h"
50 #include "BattleGroundWS.h"
51 #include "VMapFactory.h"
52 #include "Language.h"
53 #include "SocialMgr.h"
54 #include "Util.h"
55 #include "TemporarySummon.h"
56 #include "ScriptCalls.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD
102 &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused
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::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED
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::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
148 &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
149 &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
150 &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
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::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER
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::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectNULL, //156 Add Socket
217 &Spell::EffectNULL, //157 create/learn random item/spell for profession
218 &Spell::EffectMilling, //158 milling
219 &Spell::EffectNULL //159 allow rename pet once again
222 void Spell::EffectNULL(uint32 /*i*/)
224 sLog.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32 /*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i)
234 if(!unitTarget || unitTarget->isAlive())
235 return;
237 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
238 return;
240 if(!unitTarget->IsInWorld())
241 return;
243 Player* pTarget = ((Player*)unitTarget);
245 if(pTarget->isRessurectRequested()) // already have one active request
246 return;
248 uint32 health = damage;
249 uint32 mana = m_spellInfo->EffectMiscValue[i];
250 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
251 SendResurrectRequest(pTarget);
254 void Spell::EffectInstaKill(uint32 /*i*/)
256 if( !unitTarget || !unitTarget->isAlive() )
257 return;
259 // Demonic Sacrifice
260 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
262 uint32 entry = unitTarget->GetEntry();
263 uint32 spellID;
264 switch(entry)
266 case 416: spellID=18789; break; //imp
267 case 417: spellID=18792; break; //fellhunter
268 case 1860: spellID=18790; break; //void
269 case 1863: spellID=18791; break; //succubus
270 case 17252: spellID=35701; break; //fellguard
271 default:
272 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
273 return;
276 m_caster->CastSpell(m_caster,spellID,true);
279 if(m_caster==unitTarget) // prevent interrupt message
280 finish();
282 uint32 health = unitTarget->GetHealth();
283 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i)
288 uint32 absorb = 0;
289 uint32 resist = 0;
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
296 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
298 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
299 if(m_caster->GetTypeId() == TYPEID_PLAYER)
300 ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
303 void Spell::EffectSchoolDMG(uint32 effect_idx)
305 if( unitTarget && unitTarget->isAlive())
307 switch(m_spellInfo->SpellFamilyName)
309 case SPELLFAMILY_GENERIC:
311 //Gore
312 if(m_spellInfo->SpellIconID == 2269 )
314 damage+= rand()%2 ? damage : 0;
317 switch(m_spellInfo->Id) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
346 break;
349 case SPELLFAMILY_MAGE:
351 // Arcane Blast
352 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
354 m_caster->CastSpell(m_caster,36032,true);
356 break;
358 case SPELLFAMILY_WARRIOR:
360 // Bloodthirst
361 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
363 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
365 // Shield Slam
366 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
367 damage += int32(m_caster->GetShieldBlockValue());
368 // Victory Rush
369 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
371 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
372 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
374 break;
376 case SPELLFAMILY_WARLOCK:
378 // Incinerate Rank 1 & 2
379 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
381 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
382 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
383 damage += int32(damage*0.25);
385 break;
387 case SPELLFAMILY_DRUID:
389 // Ferocious Bite
390 if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
392 // converts each extra point of energy into ($f1+$AP/630) additional damage
393 float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
394 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
395 m_caster->SetPower(POWER_ENERGY,0);
397 // Rake
398 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
400 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
402 // Swipe
403 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
405 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
407 // Starfire
408 else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
410 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
411 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
413 // Starfire Bonus (caster)
414 switch((*i)->GetModifier()->m_miscvalue)
416 case 5481: // Nordrassil Regalia - bonus
418 Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
419 for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
421 // Moonfire or Insect Swarm (target debuff from any casters)
422 if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
424 int32 mod = (*i)->GetModifier()->m_amount;
425 damage += damage*mod/100;
426 break;
429 break;
431 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
433 damage += (*i)->GetModifier()->m_amount;
434 break;
439 //Mangle Bonus for the initial damage of Lacerate and Rake
440 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
441 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
443 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
444 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
445 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
447 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
448 break;
451 break;
453 case SPELLFAMILY_ROGUE:
455 // Envenom
456 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
458 // consume from stack dozes not more that have combo-points
459 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
461 // count consumed deadly poison doses at target
462 uint32 doses = 0;
464 // remove consumed poison doses
465 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
466 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
468 // Deadly poison (only attacker applied)
469 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
470 (*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
472 --combo;
473 ++doses;
475 unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
477 itr = auras.begin();
479 else
480 ++itr;
483 damage *= doses;
484 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
486 // Eviscerate and Envenom Bonus Damage (item set effect)
487 if(m_caster->GetDummyAura(37169))
488 damage += ((Player*)m_caster)->GetComboPoints()*40;
491 // Eviscerate
492 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
494 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
496 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
498 // Eviscerate and Envenom Bonus Damage (item set effect)
499 if(m_caster->GetDummyAura(37169))
500 damage += combo*40;
503 break;
505 case SPELLFAMILY_HUNTER:
507 // Mongoose Bite
508 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
510 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
512 // Arcane Shot
513 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
515 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
517 // Steady Shot
518 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
520 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
521 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
523 //Explosive Trap Effect
524 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
526 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
528 break;
530 case SPELLFAMILY_PALADIN:
532 //Judgement of Vengeance
533 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
535 uint32 stacks = 0;
536 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
537 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
538 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
539 ++stacks;
540 if(!stacks)
541 //No damage if the target isn't affected by this
542 damage = -1;
543 else
544 damage *= stacks;
546 break;
550 if(damage >= 0)
552 uint32 finalDamage;
553 if(m_originalCaster) // m_caster only passive source of cast
554 finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
555 else
556 finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
558 // post effects
559 switch(m_spellInfo->SpellFamilyName)
561 case SPELLFAMILY_WARRIOR:
563 // Bloodthirst
564 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
566 uint32 BTAura = 0;
567 switch(m_spellInfo->Id)
569 case 23881: BTAura = 23885; break;
570 case 23892: BTAura = 23886; break;
571 case 23893: BTAura = 23887; break;
572 case 23894: BTAura = 23888; break;
573 case 25251: BTAura = 25252; break;
574 case 30335: BTAura = 30339; break;
575 default:
576 sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
577 break;
580 if (BTAura)
581 m_caster->CastSpell(m_caster,BTAura,true);
583 break;
585 case SPELLFAMILY_PRIEST:
587 // Shadow Word: Death
588 if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive())
589 // deals damage equal to damage done to caster if victim is not killed
590 m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false);
592 break;
594 case SPELLFAMILY_PALADIN:
596 // Judgement of Blood
597 if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153)
599 int32 damagePoint = finalDamage * 33 / 100;
600 m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
602 break;
609 void Spell::EffectDummy(uint32 i)
611 if(!unitTarget && !gameObjTarget && !itemTarget)
612 return;
614 // selection by spell family
615 switch(m_spellInfo->SpellFamilyName)
617 case SPELLFAMILY_GENERIC:
619 switch(m_spellInfo->Id )
621 case 8063: // Deviate Fish
623 if(m_caster->GetTypeId() != TYPEID_PLAYER)
624 return;
626 uint32 spell_id = 0;
627 switch(urand(1,5))
629 case 1: spell_id = 8064; break; // Sleepy
630 case 2: spell_id = 8065; break; // Invigorate
631 case 3: spell_id = 8066; break; // Shrink
632 case 4: spell_id = 8067; break; // Party Time!
633 case 5: spell_id = 8068; break; // Healthy Spirit
635 m_caster->CastSpell(m_caster,spell_id,true,NULL);
636 return;
638 case 8213: // Savory Deviate Delight
640 if(m_caster->GetTypeId() != TYPEID_PLAYER)
641 return;
643 uint32 spell_id = 0;
644 switch(urand(1,2))
646 // Flip Out - ninja
647 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
648 // Yaaarrrr - pirate
649 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
651 m_caster->CastSpell(m_caster,spell_id,true,NULL);
652 return;
654 case 8593: // Symbol of life (restore creature to life)
655 case 31225: // Shimmering Vessel (restore creature to life)
657 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
658 return;
659 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
660 return;
662 case 12162: // Deep wounds
663 case 12850: // (now good common check for this spells)
664 case 12868:
666 if(!unitTarget)
667 return;
669 float damage;
670 // DW should benefit of attack power, damage percent mods etc.
671 // TODO: check if using offhand damage is correct and if it should be divided by 2
672 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
673 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
674 else
675 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
677 switch (m_spellInfo->Id)
679 case 12850: damage *= 0.2f; break;
680 case 12162: damage *= 0.4f; break;
681 case 12868: damage *= 0.6f; break;
682 default:
683 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
684 return;
687 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
688 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
689 return;
691 case 12975: //Last Stand
693 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
694 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
695 return;
697 case 13120: // net-o-matic
699 if(!unitTarget)
700 return;
702 uint32 spell_id = 0;
704 uint32 roll = urand(0, 99);
706 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
707 spell_id = 16566;
708 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
709 spell_id = 13119;
710 else // normal root
711 spell_id = 13099;
713 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
714 return;
716 case 13567: // Dummy Trigger
718 // can be used for different aura triggering, so select by aura
719 if(!m_triggeredByAuraSpell || !unitTarget)
720 return;
722 switch(m_triggeredByAuraSpell->Id)
724 case 26467: // Persistent Shield
725 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
726 break;
727 default:
728 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
729 break;
731 return;
733 case 14185: // Preparation Rogue
735 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
736 return;
738 //immediately finishes the cooldown on certain Rogue abilities
739 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
740 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
742 uint32 classspell = itr->first;
743 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
745 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
747 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
749 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
750 data << uint32(classspell);
751 data << uint64(m_caster->GetGUID());
752 ((Player*)m_caster)->GetSession()->SendPacket(&data);
755 return;
757 case 15998: // Capture Worg Pup
758 case 29435: // Capture Female Kaliri Hatchling
760 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
761 return;
763 Creature* creatureTarget = (Creature*)unitTarget;
764 creatureTarget->setDeathState(JUST_DIED);
765 creatureTarget->RemoveCorpse();
766 creatureTarget->SetHealth(0); // just for nice GM-mode view
767 return;
769 case 16589: // Noggenfogger Elixir
771 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
772 return;
774 uint32 spell_id = 0;
775 switch(urand(1,3))
777 case 1: spell_id = 16595; break;
778 case 2: spell_id = 16593; break;
779 default:spell_id = 16591; break;
782 m_caster->CastSpell(m_caster,spell_id,true,NULL);
783 return;
785 case 17251: // Spirit Healer Res
787 if(!unitTarget || !m_originalCaster)
788 return;
790 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
792 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
793 data << unitTarget->GetGUID();
794 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
796 return;
798 case 17271: // Test Fetid Skull
800 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
801 return;
803 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
805 m_caster->CastSpell(m_caster,spell_id,true,NULL);
806 return;
808 case 20577: // Cannibalize
809 if (unitTarget)
810 m_caster->CastSpell(m_caster,20578,false,NULL);
811 return;
812 case 23019: // Crystal Prison Dummy DND
814 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
815 return;
817 Creature* creatureTarget = (Creature*)unitTarget;
818 if(creatureTarget->isPet())
819 return;
821 creatureTarget->setDeathState(JUST_DIED);
822 creatureTarget->RemoveCorpse();
823 creatureTarget->SetHealth(0); // just for nice GM-mode view
825 GameObject* pGameObj = new GameObject;
827 Map *map = creatureTarget->GetMap();
829 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map,
830 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
831 creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) )
833 delete pGameObj;
834 return;
837 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
838 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
839 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
840 pGameObj->SetSpellId(m_spellInfo->Id);
842 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
843 map->Add(pGameObj);
845 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
846 data << uint64(pGameObj->GetGUID());
847 m_caster->SendMessageToSet(&data,true);
849 return;
851 case 23074: // Arc. Dragonling
852 if (!m_CastItem) return;
853 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
854 return;
855 case 23075: // Mithril Mechanical Dragonling
856 if (!m_CastItem) return;
857 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
858 return;
859 case 23076: // Mechanical Dragonling
860 if (!m_CastItem) return;
861 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
862 return;
863 case 23133: // Gnomish Battle Chicken
864 if (!m_CastItem) return;
865 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
866 return;
867 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
869 int32 r = irand(0, 119);
870 if ( r < 20 ) // 1/6 polymorph
871 m_caster->CastSpell(m_caster,23444,true);
872 else if ( r < 100 ) // 4/6 evil twin
873 m_caster->CastSpell(m_caster,23445,true);
874 else // 1/6 miss the target
875 m_caster->CastSpell(m_caster,36902,true);
876 return;
878 case 23453: // Ultrasafe Transporter: Gadgetzan
879 if ( roll_chance_i(50) ) // success
880 m_caster->CastSpell(m_caster,23441,true);
881 else // failure
882 m_caster->CastSpell(m_caster,23446,true);
883 return;
884 case 23645: // Hourglass Sand
885 m_caster->RemoveAurasDueToSpell(23170);
886 return;
887 case 23725: // Gift of Life (warrior bwl trinket)
888 m_caster->CastSpell(m_caster,23782,true);
889 m_caster->CastSpell(m_caster,23783,true);
890 return;
891 case 25860: // Reindeer Transformation
893 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
894 return;
896 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
897 float speed = m_caster->GetSpeedRate(MOVE_RUN);
899 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
901 //5 different spells used depending on mounted speed and if mount can fly or not
902 if (flyspeed >= 4.1f)
903 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
904 else if (flyspeed >= 3.8f)
905 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
906 else if (flyspeed >= 1.6f)
907 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
908 else if (speed >= 2.0f)
909 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
910 else
911 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
913 return;
915 //case 26074: // Holiday Cheer
916 // return; -- implemented at client side
917 case 28006: // Arcane Cloaking
919 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
920 m_caster->CastSpell(unitTarget,29294,true);
921 return;
923 case 28730: // Arcane Torrent (Mana)
925 int32 count = 0;
926 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
927 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
928 if ((*i)->GetId() == 28734)
929 ++count;
930 if (count)
932 m_caster->RemoveAurasDueToSpell(28734);
933 int32 bp = damage * count;
934 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
936 return;
938 case 29200: // Purify Helboar Meat
940 if( m_caster->GetTypeId() != TYPEID_PLAYER )
941 return;
943 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
945 m_caster->CastSpell(m_caster,spell_id,true,NULL);
946 return;
948 case 29858: // Soulshatter
949 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
950 m_caster->CastSpell(unitTarget,32835,true);
951 return;
952 case 30458: // Nigh Invulnerability
953 if (!m_CastItem) return;
954 if(roll_chance_i(86)) // success
955 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
956 else // backfire in 14% casts
957 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
958 return;
959 case 30507: // Poultryizer
960 if (!m_CastItem) return;
961 if(roll_chance_i(80)) // success
962 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
963 else // backfire 20%
964 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
965 return;
966 case 33060: // Make a Wish
968 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
969 return;
971 uint32 spell_id = 0;
973 switch(urand(1,5))
975 case 1: spell_id = 33053; break;
976 case 2: spell_id = 33057; break;
977 case 3: spell_id = 33059; break;
978 case 4: spell_id = 33062; break;
979 case 5: spell_id = 33064; break;
982 m_caster->CastSpell(m_caster,spell_id,true,NULL);
983 return;
985 case 35745:
987 uint32 spell_id;
988 switch(m_caster->GetAreaId())
990 case 3900: spell_id = 35743; break;
991 case 3742: spell_id = 35744; break;
992 default: return;
995 m_caster->CastSpell(m_caster,spell_id,true);
996 return;
998 case 37674: // Chaos Blast
1000 if(!unitTarget)
1001 return;
1003 int32 basepoints0 = 100;
1004 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
1005 return;
1007 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1009 // selecting one from Bloodstained Fortune item
1010 uint32 newitemid;
1011 switch(urand(1,20))
1013 case 1: newitemid = 32688; break;
1014 case 2: newitemid = 32689; break;
1015 case 3: newitemid = 32690; break;
1016 case 4: newitemid = 32691; break;
1017 case 5: newitemid = 32692; break;
1018 case 6: newitemid = 32693; break;
1019 case 7: newitemid = 32700; break;
1020 case 8: newitemid = 32701; break;
1021 case 9: newitemid = 32702; break;
1022 case 10: newitemid = 32703; break;
1023 case 11: newitemid = 32704; break;
1024 case 12: newitemid = 32705; break;
1025 case 13: newitemid = 32706; break;
1026 case 14: newitemid = 32707; break;
1027 case 15: newitemid = 32708; break;
1028 case 16: newitemid = 32709; break;
1029 case 17: newitemid = 32710; break;
1030 case 18: newitemid = 32711; break;
1031 case 19: newitemid = 32712; break;
1032 case 20: newitemid = 32713; break;
1033 default:
1034 return;
1037 DoCreateItem(i,newitemid);
1038 return;
1040 // Demon Broiled Surprise
1041 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1042 case 43723:
1044 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1045 return;
1047 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1048 return;
1051 case 44875: // Complete Raptor Capture
1053 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1054 return;
1056 Creature* creatureTarget = (Creature*)unitTarget;
1058 creatureTarget->setDeathState(JUST_DIED);
1059 creatureTarget->RemoveCorpse();
1060 creatureTarget->SetHealth(0); // just for nice GM-mode view
1062 //cast spell Raptor Capture Credit
1063 m_caster->CastSpell(m_caster,42337,true,NULL);
1064 return;
1066 case 37573: //Temporal Phase Modulator
1068 if(!unitTarget)
1069 return;
1071 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1072 if(!tempSummon)
1073 return;
1075 uint32 health = tempSummon->GetHealth();
1076 const uint32 entry_list[6] = {21821, 21820, 21817};
1078 float x = tempSummon->GetPositionX();
1079 float y = tempSummon->GetPositionY();
1080 float z = tempSummon->GetPositionZ();
1081 float o = tempSummon->GetOrientation();
1083 tempSummon->UnSummon();
1085 Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1086 if (!pCreature)
1087 return;
1089 pCreature->SetHealth(health);
1091 if(pCreature->AI())
1092 pCreature->AI()->AttackStart(m_caster);
1094 return;
1096 case 34665: //Administer Antidote
1098 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1099 return;
1101 if(!unitTarget)
1102 return;
1104 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1105 if(!tempSummon)
1106 return;
1108 uint32 health = tempSummon->GetHealth();
1110 float x = tempSummon->GetPositionX();
1111 float y = tempSummon->GetPositionY();
1112 float z = tempSummon->GetPositionZ();
1113 float o = tempSummon->GetOrientation();
1114 tempSummon->UnSummon();
1116 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1117 if (!pCreature)
1118 return;
1120 pCreature->SetHealth(health);
1121 ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1123 if (pCreature->AI())
1124 pCreature->AI()->AttackStart(m_caster);
1126 return;
1128 case 44997: // Converting Sentry
1130 //Converted Sentry Credit
1131 m_caster->CastSpell(m_caster, 45009, true);
1132 return;
1134 case 45030: // Impale Emissary
1136 // Emissary of Hate Credit
1137 m_caster->CastSpell(m_caster, 45088, true);
1138 return;
1140 case 50243: // Teach Language
1142 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1143 return;
1145 // spell has a 1/3 chance to trigger one of the below
1146 if(roll_chance_i(66))
1147 return;
1148 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1150 // 1000001 - gnomish binary
1151 m_caster->CastSpell(m_caster, 50242, true);
1153 else
1155 // 01001000 - goblin binary
1156 m_caster->CastSpell(m_caster, 50246, true);
1159 return;
1161 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1163 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1164 return;
1166 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1167 bg->EventPlayerDroppedFlag((Player*)m_caster);
1169 m_caster->CastSpell(m_caster, 30452, true, NULL);
1170 return;
1174 //All IconID Check in there
1175 switch(m_spellInfo->SpellIconID)
1177 // Berserking (troll racial traits)
1178 case 1661:
1180 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1181 int32 melee_mod = 10;
1182 if (healthPerc <= 40)
1183 melee_mod = 30;
1184 if (healthPerc < 100 && healthPerc > 40)
1185 melee_mod = 10+(100-healthPerc)/3;
1187 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1188 int32 hasteModBasePoints1 = (5-melee_mod);
1189 int32 hasteModBasePoints2 = 5;
1191 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1192 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1193 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1194 return;
1197 break;
1199 case SPELLFAMILY_MAGE:
1200 switch(m_spellInfo->Id )
1202 case 11958: // Cold Snap
1204 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1205 return;
1207 // immediately finishes the cooldown on Frost spells
1208 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1209 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1211 if (itr->second->state == PLAYERSPELL_REMOVED)
1212 continue;
1214 uint32 classspell = itr->first;
1215 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1217 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1218 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1219 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1221 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1223 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1224 data << uint32(classspell);
1225 data << uint64(m_caster->GetGUID());
1226 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1229 return;
1231 case 32826:
1233 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1235 //Polymorph Cast Visual Rank 1
1236 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1237 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1239 return;
1242 break;
1243 case SPELLFAMILY_WARRIOR:
1244 // Charge
1245 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1247 int32 chargeBasePoints0 = damage;
1248 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1249 return;
1251 // Execute
1252 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1254 if(!unitTarget)
1255 return;
1257 int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
1258 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1259 m_caster->SetPower(POWER_RAGE,0);
1260 return;
1262 if(m_spellInfo->Id==21977) //Warrior's Wrath
1264 if(!unitTarget)
1265 return;
1267 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1268 return;
1270 break;
1271 case SPELLFAMILY_WARLOCK:
1272 //Life Tap (only it have this with dummy effect)
1273 if (m_spellInfo->SpellFamilyFlags == 0x40000)
1275 float cost = m_currentBasePoints[0]+1;
1277 if(Player* modOwner = m_caster->GetSpellModOwner())
1278 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this);
1280 int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE);
1282 if(int32(m_caster->GetHealth()) > dmg)
1284 // Shouldn't Appear in Combat Log
1285 m_caster->ModifyHealth(-dmg);
1287 int32 mana = dmg;
1289 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1290 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1292 // only Imp. Life Tap have this in combination with dummy aura
1293 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1294 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1297 m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL);
1299 // Mana Feed
1300 int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster);
1301 manaFeedVal = manaFeedVal * mana / 100;
1302 if(manaFeedVal > 0)
1303 m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL);
1305 else
1306 SendCastResult(SPELL_FAILED_FIZZLE);
1307 return;
1309 break;
1310 case SPELLFAMILY_PRIEST:
1311 switch(m_spellInfo->Id )
1313 case 28598: // Touch of Weakness triggered spell
1315 if(!unitTarget || !m_triggeredByAuraSpell)
1316 return;
1318 uint32 spellid = 0;
1319 switch(m_triggeredByAuraSpell->Id)
1321 case 2652: spellid = 2943; break; // Rank 1
1322 case 19261: spellid = 19249; break; // Rank 2
1323 case 19262: spellid = 19251; break; // Rank 3
1324 case 19264: spellid = 19252; break; // Rank 4
1325 case 19265: spellid = 19253; break; // Rank 5
1326 case 19266: spellid = 19254; break; // Rank 6
1327 case 25461: spellid = 25460; break; // Rank 7
1328 default:
1329 sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1330 return;
1332 m_caster->CastSpell(unitTarget, spellid, true, NULL);
1333 return;
1336 break;
1337 case SPELLFAMILY_DRUID:
1338 switch(m_spellInfo->Id )
1340 case 5420: // Tree of Life passive
1342 // Tree of Life area effect
1343 int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
1344 m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
1345 return;
1348 break;
1349 case SPELLFAMILY_ROGUE:
1350 switch(m_spellInfo->Id )
1352 case 31231: // Cheat Death
1354 m_caster->CastSpell(m_caster,45182,true);
1355 return;
1357 case 5938: // Shiv
1359 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1360 return;
1362 Player *pCaster = ((Player*)m_caster);
1364 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1365 if(!item)
1366 return;
1368 // all poison enchantments is temporary
1369 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1370 if(!enchant_id)
1371 return;
1373 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1374 if(!pEnchant)
1375 return;
1377 for (int s=0;s<3;s++)
1379 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1380 continue;
1382 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1383 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1384 continue;
1386 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1389 m_caster->CastSpell(unitTarget, 5940, true);
1390 return;
1393 break;
1394 case SPELLFAMILY_HUNTER:
1395 // Steady Shot
1396 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1398 if( !unitTarget || !unitTarget->isAlive())
1399 return;
1401 bool found = false;
1403 // check dazed affect
1404 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1405 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1407 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1409 found = true;
1410 break;
1414 if(found)
1415 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
1416 return;
1418 // Kill command
1419 if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
1421 if(m_caster->getClass()!=CLASS_HUNTER)
1422 return;
1424 // clear hunter crit aura state
1425 m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false);
1427 // additional damage from pet to pet target
1428 Pet* pet = m_caster->GetPet();
1429 if(!pet || !pet->getVictim())
1430 return;
1432 uint32 spell_id = 0;
1433 switch (m_spellInfo->Id)
1435 case 34026: spell_id = 34027; break; // rank 1
1436 default:
1437 sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id);
1438 return;
1441 pet->CastSpell(pet->getVictim(), spell_id, true);
1442 return;
1445 switch(m_spellInfo->Id)
1447 case 23989: //Readiness talent
1449 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1450 return;
1452 //immediately finishes the cooldown for hunter abilities
1453 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1454 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1456 uint32 classspell = itr->first;
1457 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1459 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1461 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1463 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1464 data << uint32(classspell);
1465 data << uint64(m_caster->GetGUID());
1466 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1469 return;
1471 case 37506: // Scatter Shot
1473 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1474 return;
1476 // break Auto Shot and autohit
1477 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1478 m_caster->AttackStop();
1479 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1480 return;
1483 break;
1484 case SPELLFAMILY_PALADIN:
1485 switch(m_spellInfo->SpellIconID)
1487 case 156: // Holy Shock
1489 if(!unitTarget)
1490 return;
1492 int hurt = 0;
1493 int heal = 0;
1495 switch(m_spellInfo->Id)
1497 case 20473: hurt = 25912; heal = 25914; break;
1498 case 20929: hurt = 25911; heal = 25913; break;
1499 case 20930: hurt = 25902; heal = 25903; break;
1500 case 27174: hurt = 27176; heal = 27175; break;
1501 case 33072: hurt = 33073; heal = 33074; break;
1502 default:
1503 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1504 return;
1507 if(m_caster->IsFriendlyTo(unitTarget))
1508 m_caster->CastSpell(unitTarget, heal, true, 0);
1509 else
1510 m_caster->CastSpell(unitTarget, hurt, true, 0);
1512 return;
1514 case 561: // Judgement of command
1516 if(!unitTarget)
1517 return;
1519 uint32 spell_id = m_currentBasePoints[i]+1;
1520 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1521 if(!spell_proto)
1522 return;
1524 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1526 // decreased damage (/2) for non-stunned target.
1527 SpellModifier *mod = new SpellModifier;
1528 mod->op = SPELLMOD_DAMAGE;
1529 mod->value = -50;
1530 mod->type = SPELLMOD_PCT;
1531 mod->spellId = m_spellInfo->Id;
1532 mod->mask = 0x0000020000000000LL;
1533 mod->mask2= 0LL;
1535 ((Player*)m_caster)->AddSpellMod(mod, true);
1536 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1537 // mod deleted
1538 ((Player*)m_caster)->AddSpellMod(mod, false);
1540 else
1541 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1543 return;
1547 switch(m_spellInfo->Id)
1549 case 31789: // Righteous Defense (step 1)
1551 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1553 // non-standard cast requirement check
1554 if (!unitTarget || unitTarget->getAttackers().empty())
1556 // clear cooldown at fail
1557 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1559 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1561 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1562 data << uint32(m_spellInfo->Id);
1563 data << uint64(m_caster->GetGUID());
1564 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1567 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1568 return;
1571 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1572 // Clear targets for eff 1
1573 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1574 ihit->effectMask &= ~(1<<1);
1576 // not empty (checked)
1577 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1579 // chance to be selected from list
1580 float chance = 100.0f/attackers.size();
1581 uint32 count=0;
1582 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1584 if(!roll_chance_f(chance))
1585 continue;
1586 ++count;
1587 AddUnitTarget((*aItr), 1);
1590 // now let next effect cast spell at each target.
1591 return;
1593 case 37877: // Blessing of Faith
1595 if(!unitTarget)
1596 return;
1598 uint32 spell_id = 0;
1599 switch(unitTarget->getClass())
1601 case CLASS_DRUID: spell_id = 37878; break;
1602 case CLASS_PALADIN: spell_id = 37879; break;
1603 case CLASS_PRIEST: spell_id = 37880; break;
1604 case CLASS_SHAMAN: spell_id = 37881; break;
1605 default: return; // ignore for not healing classes
1608 m_caster->CastSpell(m_caster,spell_id,true);
1609 return;
1612 break;
1613 case SPELLFAMILY_SHAMAN:
1614 //Shaman Rockbiter Weapon
1615 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1617 uint32 spell_id = 0;
1618 switch(m_spellInfo->Id)
1620 case 8017: spell_id = 36494; break; // Rank 1
1621 case 8018: spell_id = 36750; break; // Rank 2
1622 case 8019: spell_id = 36755; break; // Rank 3
1623 case 10399: spell_id = 36759; break; // Rank 4
1624 case 16314: spell_id = 36763; break; // Rank 5
1625 case 16315: spell_id = 36766; break; // Rank 6
1626 case 16316: spell_id = 36771; break; // Rank 7
1627 case 25479: spell_id = 36775; break; // Rank 8
1628 case 25485: spell_id = 36499; break; // Rank 9
1629 default:
1630 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1631 return;
1634 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1636 if(!spellInfo)
1638 sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1639 return;
1642 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1643 return;
1645 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1647 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1649 if(item->IsFitToSpellRequirements(m_spellInfo))
1651 Spell *spell = new Spell(m_caster, spellInfo, true);
1653 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1654 // at calculation applied affect from Elemental Weapons talent
1655 // real enchantment damage-1
1656 spell->m_currentBasePoints[1] = damage-1;
1658 SpellCastTargets targets;
1659 targets.setItemTarget( item );
1660 spell->prepare(&targets);
1664 return;
1667 if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect
1669 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1670 return;
1672 // Regenerate 6% of Total Mana Every 3 secs
1673 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1674 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1675 return;
1678 break;
1681 // pet auras
1682 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1684 m_caster->AddPetAura(petSpell);
1685 return;
1689 void Spell::EffectTriggerSpellWithValue(uint32 i)
1691 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1693 // normal case
1694 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1696 if(!spellInfo)
1698 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1699 return;
1702 int32 bp = damage;
1703 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1706 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1708 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1709 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1711 if(!spellInfo)
1713 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1714 return;
1717 finish();
1718 Spell *spell = new Spell(m_caster, spellInfo, true);
1720 SpellCastTargets targets;
1721 targets.setUnitTarget( unitTarget);
1722 spell->prepare(&targets);
1724 m_caster->SetCurrentCastedSpell(spell);
1725 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1729 void Spell::EffectForceCast(uint32 i)
1731 if( !unitTarget )
1732 return;
1734 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1736 // normal case
1737 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1739 if(!spellInfo)
1741 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1742 return;
1745 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1748 void Spell::EffectTriggerSpell(uint32 i)
1750 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1752 // special cases
1753 switch(triggered_spell_id)
1755 // Vanish
1756 case 18461:
1758 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1759 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1760 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1762 // if this spell is given to NPC it must handle rest by it's own AI
1763 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1764 return;
1766 // get highest rank of the Stealth spell
1767 uint32 spellId = 0;
1768 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1769 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1771 // only highest rank is shown in spell book, so simply check if shown in spell book
1772 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1773 continue;
1775 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1776 if (!spellInfo)
1777 continue;
1779 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1781 spellId = spellInfo->Id;
1782 break;
1786 // no Stealth spell found
1787 if (!spellId)
1788 return;
1790 // reset cooldown on it if needed
1791 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1792 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1794 m_caster->CastSpell(m_caster, spellId, true);
1795 return;
1797 // just skip
1798 case 23770: // Sayge's Dark Fortune of *
1799 // not exist, common cooldown can be implemented in scripts if need.
1800 return;
1801 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1802 case 29284:
1804 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1805 if (!spell)
1806 return;
1808 for (int i=0; i < spell->StackAmount; ++i)
1809 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1810 return;
1812 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1813 case 29286:
1815 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1816 if (!spell)
1817 return;
1819 for (int i=0; i < spell->StackAmount; ++i)
1820 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1821 return;
1823 // Righteous Defense
1824 case 31980:
1826 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1827 return;
1829 // Cloak of Shadows
1830 case 35729 :
1832 Unit::AuraMap& Auras = m_caster->GetAuras();
1833 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1835 // remove all harmful spells on you...
1836 if( // ignore positive and passive auras
1837 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1838 // ignore physical auras
1839 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 &&
1840 // ignore immunity persistent spells
1841 !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) )
1843 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1844 iter = Auras.begin();
1847 return;
1849 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1850 case 41967:
1852 if (Unit *pet = m_caster->GetPet())
1853 pet->CastSpell(pet, 28305, true);
1854 return;
1858 // normal case
1859 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1861 if(!spellInfo)
1863 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1864 return;
1867 // some triggered spells require specific equipment
1868 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1870 // main hand weapon required
1871 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1873 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1875 // skip spell if no weapon in slot or broken
1876 if(!item || item->IsBroken() )
1877 return;
1879 // skip spell if weapon not fit to triggered spell
1880 if(!item->IsFitToSpellRequirements(spellInfo))
1881 return;
1884 // offhand hand weapon required
1885 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1887 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1889 // skip spell if no weapon in slot or broken
1890 if(!item || item->IsBroken() )
1891 return;
1893 // skip spell if weapon not fit to triggered spell
1894 if(!item->IsFitToSpellRequirements(spellInfo))
1895 return;
1899 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1900 bool instant = false;
1901 for(uint32 j = i+1; j < 3; ++j)
1903 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1905 instant = true;
1906 break;
1910 if(instant)
1912 if (unitTarget)
1913 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1915 else
1916 m_TriggerSpells.push_back(spellInfo);
1919 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1921 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1923 // normal case
1924 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1926 if(!spellInfo)
1928 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1929 m_spellInfo->Id,effect_idx,triggered_spell_id);
1930 return;
1933 if (m_CastItem)
1934 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1936 Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
1938 SpellCastTargets targets;
1939 targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
1940 spell->m_CastItem = m_CastItem;
1941 spell->prepare(&targets, NULL);
1944 void Spell::EffectTeleportUnits(uint32 i)
1946 if(!unitTarget || unitTarget->isInFlight())
1947 return;
1949 switch (m_spellInfo->EffectImplicitTargetB[i])
1951 case TARGET_INNKEEPER_COORDINATES:
1953 // Only players can teleport to innkeeper
1954 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1955 return;
1957 ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
1958 return;
1960 case TARGET_TABLE_X_Y_Z_COORDINATES:
1962 // TODO: Only players can teleport?
1963 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1964 return;
1965 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
1966 if(!st)
1968 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
1969 return;
1971 ((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);
1972 break;
1974 case TARGET_BEHIND_VICTIM:
1976 // Get selected target for player (or victim for units)
1977 Unit *pTarget = NULL;
1978 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1979 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
1980 else
1981 pTarget = m_caster->getVictim();
1982 // No target present - return
1983 if (!pTarget)
1984 return;
1985 // Init dest coordinates
1986 uint32 mapid = m_caster->GetMapId();
1987 float x = m_targets.m_destX;
1988 float y = m_targets.m_destY;
1989 float z = m_targets.m_destZ;
1990 float orientation = pTarget->GetOrientation();
1991 // Teleport
1992 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1993 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
1994 else
1996 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
1997 WorldPacket data;
1998 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
1999 unitTarget->SendMessageToSet(&data, false);
2001 return;
2003 default:
2005 // If not exist data for dest location - return
2006 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2008 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2009 return;
2011 // Init dest coordinates
2012 uint32 mapid = m_caster->GetMapId();
2013 float x = m_targets.m_destX;
2014 float y = m_targets.m_destY;
2015 float z = m_targets.m_destZ;
2016 float orientation = unitTarget->GetOrientation();
2017 // Teleport
2018 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2019 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2020 else
2022 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2023 WorldPacket data;
2024 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2025 unitTarget->SendMessageToSet(&data, false);
2027 return;
2031 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2032 switch ( m_spellInfo->Id )
2034 // Dimensional Ripper - Everlook
2035 case 23442:
2037 int32 r = irand(0, 119);
2038 if ( r >= 70 ) // 7/12 success
2040 if ( r < 100 ) // 4/12 evil twin
2041 m_caster->CastSpell(m_caster,23445,true);
2042 else // 1/12 fire
2043 m_caster->CastSpell(m_caster,23449,true);
2045 return;
2047 // Ultrasafe Transporter: Toshley's Station
2048 case 36941:
2050 if ( roll_chance_i(50) ) // 50% success
2052 int32 rand_eff = urand(1,7);
2053 switch ( rand_eff )
2055 case 1:
2056 // soul split - evil
2057 m_caster->CastSpell(m_caster,36900,true);
2058 break;
2059 case 2:
2060 // soul split - good
2061 m_caster->CastSpell(m_caster,36901,true);
2062 break;
2063 case 3:
2064 // Increase the size
2065 m_caster->CastSpell(m_caster,36895,true);
2066 break;
2067 case 4:
2068 // Decrease the size
2069 m_caster->CastSpell(m_caster,36893,true);
2070 break;
2071 case 5:
2072 // Transform
2074 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2075 m_caster->CastSpell(m_caster,36897,true);
2076 else
2077 m_caster->CastSpell(m_caster,36899,true);
2078 break;
2080 case 6:
2081 // chicken
2082 m_caster->CastSpell(m_caster,36940,true);
2083 break;
2084 case 7:
2085 // evil twin
2086 m_caster->CastSpell(m_caster,23445,true);
2087 break;
2090 return;
2092 // Dimensional Ripper - Area 52
2093 case 36890:
2095 if ( roll_chance_i(50) ) // 50% success
2097 int32 rand_eff = urand(1,4);
2098 switch ( rand_eff )
2100 case 1:
2101 // soul split - evil
2102 m_caster->CastSpell(m_caster,36900,true);
2103 break;
2104 case 2:
2105 // soul split - good
2106 m_caster->CastSpell(m_caster,36901,true);
2107 break;
2108 case 3:
2109 // Increase the size
2110 m_caster->CastSpell(m_caster,36895,true);
2111 break;
2112 case 4:
2113 // Transform
2115 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2116 m_caster->CastSpell(m_caster,36897,true);
2117 else
2118 m_caster->CastSpell(m_caster,36899,true);
2119 break;
2123 return;
2128 void Spell::EffectApplyAura(uint32 i)
2130 if(!unitTarget)
2131 return;
2133 SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE];
2134 for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
2135 if(itr->type == m_spellInfo->EffectApplyAuraName[i])
2136 return;
2138 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2139 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2140 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2141 return;
2143 Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2144 if(!caster)
2145 return;
2147 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2149 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2151 // Now Reduce spell duration using data received at spell hit
2152 int32 duration = Aur->GetAuraMaxDuration();
2153 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2154 Aur->setDiminishGroup(m_diminishGroup);
2156 // if Aura removed and deleted, do not continue.
2157 if(duration== 0 && !(Aur->IsPermanent()))
2159 delete Aur;
2160 return;
2163 if(duration != Aur->GetAuraMaxDuration())
2165 Aur->SetAuraMaxDuration(duration);
2166 Aur->SetAuraDuration(duration);
2169 bool added = unitTarget->AddAura(Aur);
2171 // Aura not added and deleted in AddAura call;
2172 if (!added)
2173 return;
2175 // found crash at character loading, broken pointer to Aur...
2176 // Aur was deleted in AddAura()...
2177 if(!Aur)
2178 return;
2180 // TODO Make a way so it works for every related spell!
2181 if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players
2183 uint32 spellId = 0;
2184 if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL)
2185 spellId = 6788; // Weakened Soul
2186 else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE)
2187 spellId = 25771; // Forbearance
2188 else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA)
2189 spellId = 41425; // Hypothermia
2190 else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
2191 spellId = 11196; // Recently Bandaged
2192 else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) )
2193 spellId = 23230; // Blood Fury - Healing Reduction
2195 SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
2196 if (AdditionalSpellInfo)
2198 // applied at target by target
2199 Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0);
2200 unitTarget->AddAura(AdditionalAura);
2201 sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
2205 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2206 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2207 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2210 void Spell::EffectUnlearnSpecialization( uint32 i )
2212 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2213 return;
2215 Player *_player = (Player*)unitTarget;
2216 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2218 _player->removeSpell(spellToUnlearn);
2220 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2223 void Spell::EffectPowerDrain(uint32 i)
2225 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2226 return;
2228 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2230 if(!unitTarget)
2231 return;
2232 if(!unitTarget->isAlive())
2233 return;
2234 if(unitTarget->getPowerType() != drain_power)
2235 return;
2236 if(damage < 0)
2237 return;
2239 uint32 curPower = unitTarget->GetPower(drain_power);
2241 //add spell damage bonus
2242 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2244 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2245 uint32 power = damage;
2246 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2247 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2249 int32 new_damage;
2250 if(curPower < power)
2251 new_damage = curPower;
2252 else
2253 new_damage = power;
2255 unitTarget->ModifyPower(drain_power,-new_damage);
2257 if(drain_power == POWER_MANA)
2259 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2260 if(manaMultiplier==0)
2261 manaMultiplier = 1;
2263 if(Player *modOwner = m_caster->GetSpellModOwner())
2264 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2266 int32 gain = int32(new_damage*manaMultiplier);
2268 m_caster->ModifyPower(POWER_MANA,gain);
2269 //send log
2270 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2274 void Spell::EffectSendEvent(uint32 EffectIndex)
2276 if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2278 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2279 if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2281 switch(m_spellInfo->Id)
2283 case 23333: // Pickup Horde Flag
2284 /*do not uncomment .
2285 if(bg->GetTypeID()==BATTLEGROUND_WS)
2286 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2287 sLog.outDebug("Send Event Horde Flag Picked Up");
2288 break;
2289 /* not used :
2290 case 23334: // Drop Horde Flag
2291 if(bg->GetTypeID()==BATTLEGROUND_WS)
2292 bg->EventPlayerDroppedFlag((Player*)m_caster);
2293 sLog.outDebug("Drop Horde Flag");
2294 break;
2296 case 23335: // Pickup Alliance Flag
2297 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2298 if(bg->GetTypeID()==BATTLEGROUND_WS)
2299 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2300 sLog.outDebug("Send Event Alliance Flag Picked Up");
2301 break;
2302 /* not used :
2303 case 23336: // Drop Alliance Flag
2304 if(bg->GetTypeID()==BATTLEGROUND_WS)
2305 bg->EventPlayerDroppedFlag((Player*)m_caster);
2306 sLog.outDebug("Drop Alliance Flag");
2307 break;
2308 case 23385: // Alliance Flag Returns
2309 if(bg->GetTypeID()==BATTLEGROUND_WS)
2310 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2311 sLog.outDebug("Alliance Flag Returned");
2312 break;
2313 case 23386: // Horde Flag Returns
2314 if(bg->GetTypeID()==BATTLEGROUND_WS)
2315 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2316 sLog.outDebug("Horde Flag Returned");
2317 break;*/
2318 case 34976:
2320 if(bg->GetTypeID()==BATTLEGROUND_EY)
2321 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2323 break;
2324 default:
2325 sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2326 break;
2330 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2331 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2334 void Spell::EffectPowerBurn(uint32 i)
2336 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2337 return;
2339 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2341 if(!unitTarget)
2342 return;
2343 if(!unitTarget->isAlive())
2344 return;
2345 if(unitTarget->getPowerType()!=powertype)
2346 return;
2347 if(damage < 0)
2348 return;
2350 int32 curPower = int32(unitTarget->GetPower(powertype));
2352 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2353 uint32 power = damage;
2354 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2355 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2357 int32 new_damage = (curPower < power) ? curPower : power;
2359 unitTarget->ModifyPower(powertype,-new_damage);
2360 float multiplier = m_spellInfo->EffectMultipleValue[i];
2362 if(Player *modOwner = m_caster->GetSpellModOwner())
2363 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2365 new_damage = int32(new_damage*multiplier);
2366 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2369 void Spell::EffectHeal( uint32 /*i*/ )
2371 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2373 // Try to get original caster
2374 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2376 // Skip if m_originalCaster not available
2377 if (!caster)
2378 return;
2380 int32 addhealth = damage;
2382 // Vessel of the Naaru (Vial of the Sunwell trinket)
2383 if (m_spellInfo->Id == 45064)
2385 // Amount of heal - depends from stacked Holy Energy
2386 int damageAmount = 0;
2387 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2388 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2389 if((*i)->GetId() == 45062)
2390 damageAmount+=(*i)->GetModifier()->m_amount;
2391 if (damageAmount)
2392 m_caster->RemoveAurasDueToSpell(45062);
2394 addhealth += damageAmount;
2396 // Swiftmend - consumes Regrowth or Rejuvenation
2397 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2399 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2400 // find most short by duration
2401 Aura *targetAura = NULL;
2402 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2404 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2405 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2407 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2408 targetAura = *i;
2412 if(!targetAura)
2414 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2415 return;
2417 int idx = 0;
2418 while(idx < 3)
2420 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2421 break;
2422 idx++;
2425 int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget);
2426 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2427 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2429 addhealth += tickheal * tickcount;
2431 else
2432 addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2434 bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType);
2435 if (crit)
2436 addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget);
2437 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit);
2439 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2440 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2442 if(caster->GetTypeId()==TYPEID_PLAYER)
2443 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2444 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2446 // ignore item heals
2447 if(m_CastItem)
2448 return;
2450 uint32 procHealer = PROC_FLAG_HEAL;
2451 if (crit)
2452 procHealer |= PROC_FLAG_CRIT_HEAL;
2454 m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell);
2458 void Spell::EffectHealPct( uint32 /*i*/ )
2460 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2462 // Try to get original caster
2463 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2465 // Skip if m_originalCaster not available
2466 if (!caster)
2467 return;
2469 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2470 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2472 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2473 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2475 if(caster->GetTypeId()==TYPEID_PLAYER)
2476 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2477 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2481 void Spell::EffectHealMechanical( uint32 /*i*/ )
2483 // Mechanic creature type should be correctly checked by targetCreatureType field
2484 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2486 // Try to get original caster
2487 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2489 // Skip if m_originalCaster not available
2490 if (!caster)
2491 return;
2493 uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
2494 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2495 unitTarget->ModifyHealth( int32(damage) );
2499 void Spell::EffectHealthLeech(uint32 i)
2501 if(!unitTarget)
2502 return;
2503 if(!unitTarget->isAlive())
2504 return;
2506 if(damage < 0)
2507 return;
2509 sLog.outDebug("HealthLeech :%i", damage);
2511 float multiplier = m_spellInfo->EffectMultipleValue[i];
2513 if(Player *modOwner = m_caster->GetSpellModOwner())
2514 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2516 int32 new_damage = int32(damage*multiplier);
2517 uint32 curHealth = unitTarget->GetHealth();
2518 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2519 if(curHealth < new_damage)
2520 new_damage = curHealth;
2522 if(m_caster->isAlive())
2524 new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
2526 m_caster->ModifyHealth(new_damage);
2528 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2529 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2533 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2535 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2536 return;
2538 Player* player = (Player*)unitTarget;
2540 uint32 newitemid = itemtype;
2541 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2542 if(!pProto)
2544 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2545 return;
2548 uint32 num_to_add;
2550 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2551 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2553 int32 basePoints = m_currentBasePoints[i];
2554 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2555 if (randomPoints)
2556 num_to_add = basePoints + irand(1, randomPoints);
2557 else
2558 num_to_add = basePoints + 1;
2560 else if (pProto->MaxCount == 1)
2561 num_to_add = 1;
2562 else if(player->getLevel() >= m_spellInfo->spellLevel)
2564 int32 basePoints = m_currentBasePoints[i];
2565 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2566 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2568 else
2569 num_to_add = 2;
2571 if (num_to_add < 1)
2572 num_to_add = 1;
2573 if (num_to_add > pProto->Stackable)
2574 num_to_add = pProto->Stackable;
2576 // init items_count to 1, since 1 item will be created regardless of specialization
2577 int items_count=1;
2578 // the chance to create additional items
2579 float additionalCreateChance=0.0f;
2580 // the maximum number of created additional items
2581 uint8 additionalMaxNum=0;
2582 // get the chance and maximum number for creating extra items
2583 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2585 // roll with this chance till we roll not to create or we create the max num
2586 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2587 ++items_count;
2590 // really will be created more items
2591 num_to_add *= items_count;
2593 // can the player store the new item?
2594 ItemPosCountVec dest;
2595 uint32 no_space = 0;
2596 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2597 if( msg != EQUIP_ERR_OK )
2599 // convert to possible store amount
2600 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2601 num_to_add -= no_space;
2602 else
2604 // if not created by another reason from full inventory or unique items amount limitation
2605 player->SendEquipError( msg, NULL, NULL );
2606 return;
2610 if(num_to_add)
2612 // create the new item and store it
2613 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2615 // was it successful? return error if not
2616 if(!pItem)
2618 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2619 return;
2622 // set the "Crafted by ..." property of the item
2623 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2624 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2626 // send info to the client
2627 if(pItem)
2628 player->SendNewItem(pItem, num_to_add, true, true);
2630 // we succeeded in creating at least one item, so a levelup is possible
2631 player->UpdateCraftSkill(m_spellInfo->Id);
2634 // for battleground marks send by mail if not add all expected
2635 if(no_space > 0 )
2637 BattleGroundTypeId bgType;
2638 switch(m_spellInfo->Id)
2640 case SPELL_AV_MARK_WINNER:
2641 case SPELL_AV_MARK_LOSER:
2642 bgType = BATTLEGROUND_AV;
2643 break;
2644 case SPELL_WS_MARK_WINNER:
2645 case SPELL_WS_MARK_LOSER:
2646 bgType = BATTLEGROUND_WS;
2647 break;
2648 case SPELL_AB_MARK_WINNER:
2649 case SPELL_AB_MARK_LOSER:
2650 bgType = BATTLEGROUND_AB;
2651 break;
2652 default:
2653 return;
2656 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2657 bg->SendRewardMarkByMail(player,newitemid,no_space);
2661 void Spell::EffectCreateItem(uint32 i)
2663 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2666 void Spell::EffectPersistentAA(uint32 i)
2668 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2670 if(Player* modOwner = m_caster->GetSpellModOwner())
2671 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2673 int32 duration = GetSpellDuration(m_spellInfo);
2674 DynamicObject* dynObj = new DynamicObject;
2675 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2677 delete dynObj;
2678 return;
2680 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2681 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2682 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2683 m_caster->AddDynObject(dynObj);
2684 dynObj->GetMap()->Add(dynObj);
2687 void Spell::EffectEnergize(uint32 i)
2689 if(!unitTarget)
2690 return;
2691 if(!unitTarget->isAlive())
2692 return;
2694 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2695 return;
2697 // Some level depends spells
2698 int multiplier = 0;
2699 int level_diff = 0;
2700 switch (m_spellInfo->Id)
2702 // Restore Energy
2703 case 9512:
2704 level_diff = m_caster->getLevel() - 40;
2705 multiplier = 2;
2706 break;
2707 // Blood Fury
2708 case 24571:
2709 level_diff = m_caster->getLevel() - 60;
2710 multiplier = 10;
2711 break;
2712 // Burst of Energy
2713 case 24532:
2714 level_diff = m_caster->getLevel() - 60;
2715 multiplier = 4;
2716 break;
2717 default:
2718 break;
2721 if (level_diff > 0)
2722 damage -= multiplier * level_diff;
2724 if(damage < 0)
2725 return;
2727 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2729 if(unitTarget->GetMaxPower(power) == 0)
2730 return;
2732 unitTarget->ModifyPower(power,damage);
2733 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2735 // Mad Alchemist's Potion
2736 if (m_spellInfo->Id == 45051)
2738 // find elixirs on target
2739 uint32 elixir_mask = 0;
2740 Unit::AuraMap& Auras = unitTarget->GetAuras();
2741 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2743 uint32 spell_id = itr->second->GetId();
2744 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2745 elixir_mask |= mask;
2748 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2749 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2751 // get all available elixirs by mask and spell level
2752 std::vector<uint32> elixirs;
2753 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2754 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2756 if (itr->second & elixir_mask)
2758 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2759 continue;
2761 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2762 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2763 continue;
2765 elixirs.push_back(itr->first);
2769 if (!elixirs.empty())
2771 // cast random elixir on target
2772 uint32 rand_spell = urand(0,elixirs.size()-1);
2773 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2778 void Spell::EffectEnergisePct(uint32 i)
2780 if(!unitTarget)
2781 return;
2782 if(!unitTarget->isAlive())
2783 return;
2785 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2786 return;
2788 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2790 uint32 maxPower = unitTarget->GetMaxPower(power);
2791 if(maxPower == 0)
2792 return;
2794 uint32 gain = damage * maxPower / 100;
2795 unitTarget->ModifyPower(power, gain);
2796 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2799 void Spell::SendLoot(uint64 guid, LootType loottype)
2801 Player* player = (Player*)m_caster;
2802 if (!player)
2803 return;
2805 if (gameObjTarget)
2807 if (Script->GOHello(player, gameObjTarget))
2808 return;
2810 switch (gameObjTarget->GetGoType())
2812 case GAMEOBJECT_TYPE_DOOR:
2813 case GAMEOBJECT_TYPE_BUTTON:
2814 gameObjTarget->UseDoorOrButton();
2815 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2816 return;
2818 case GAMEOBJECT_TYPE_QUESTGIVER:
2819 // start or end quest
2820 player->PrepareQuestMenu(guid);
2821 player->SendPreparedQuest(guid);
2822 return;
2824 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2825 // triggering linked GO
2826 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2827 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2828 return;
2830 case GAMEOBJECT_TYPE_GOOBER:
2831 // goober_scripts can be triggered if the player don't have the quest
2832 if (gameObjTarget->GetGOInfo()->goober.eventId)
2834 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2835 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2838 // cast goober spell
2839 if (gameObjTarget->GetGOInfo()->goober.questId)
2840 ///Quest require to be active for GO using
2841 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2842 return;
2844 gameObjTarget->AddUniqueUse(player);
2845 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2847 //TODO? Objective counting called without spell check but with quest objective check
2848 // if send spell id then this line will duplicate to spell casting call (double counting)
2849 // So we or have this line and not required in quest_template have reqSpellIdN
2850 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2851 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2853 // triggering linked GO
2854 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2855 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2857 return;
2859 case GAMEOBJECT_TYPE_CHEST:
2860 // TODO: possible must be moved to loot release (in different from linked triggering)
2861 if (gameObjTarget->GetGOInfo()->chest.eventId)
2863 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2864 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2867 // triggering linked GO
2868 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2869 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2871 // Don't return, let loots been taken
2875 // Send loot
2876 player->SendLoot(guid, loottype);
2879 void Spell::EffectOpenLock(uint32 /*i*/)
2881 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2883 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2884 return;
2887 Player* player = (Player*)m_caster;
2889 LootType loottype = LOOT_CORPSE;
2890 uint32 lockId = 0;
2891 uint64 guid = 0;
2893 // Get lockId
2894 if(gameObjTarget)
2896 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2897 // Arathi Basin banner opening !
2898 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2899 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2901 //isAllowUseBattleGroundObject() already called in CanCast()
2902 // in battleground check
2903 if(BattleGround *bg = player->GetBattleGround())
2905 // check if it's correct bg
2906 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2907 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2908 return;
2911 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2913 //isAllowUseBattleGroundObject() already called in CanCast()
2914 // in battleground check
2915 if(BattleGround *bg = player->GetBattleGround())
2917 if(bg->GetTypeID() == BATTLEGROUND_EY)
2918 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2919 return;
2922 lockId = gameObjTarget->GetLockId();
2923 guid = gameObjTarget->GetGUID();
2925 else if(itemTarget)
2927 lockId = itemTarget->GetProto()->LockID;
2928 guid = itemTarget->GetGUID();
2930 else
2932 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2933 return;
2936 if(!lockId) // possible case for GO and maybe for items.
2938 SendLoot(guid, loottype);
2939 return;
2942 // Get LockInfo
2943 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2945 if (!lockInfo)
2947 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2948 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2949 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2950 return;
2953 // check key
2954 for(int i = 0; i < 8; ++i)
2956 // Type==1 This means lockInfo->Index[i] is an item
2957 if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
2959 SendLoot(guid, loottype);
2960 return;
2964 uint32 SkillId = 0;
2965 // Check and skill-up skill
2966 if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2967 SkillId = m_spellInfo->EffectMiscValue[1];
2968 // pickpocketing spells
2969 else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
2970 SkillId = SKILL_LOCKPICKING;
2972 // skill bonus provided by casting spell (mostly item spells)
2973 uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
2975 uint32 reqSkillValue = lockInfo->Skill[0];
2977 if(lockInfo->Skill[1]) // required pick lock skill applying
2979 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
2981 SendCastResult(SPELL_FAILED_FIZZLE);
2982 return;
2985 reqSkillValue = lockInfo->Skill[1];
2987 else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
2989 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2990 return;
2993 if ( SkillId )
2995 loottype = LOOT_SKINNING;
2996 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
2998 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
2999 return;
3002 // update skill if really known
3003 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3004 if(SkillValue) // non only item base skill
3006 if(gameObjTarget)
3008 // Allow one skill-up until respawned
3009 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3010 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
3011 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3013 else if(itemTarget)
3015 // Do one skill-up
3016 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3017 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3022 SendLoot(guid, loottype);
3025 void Spell::EffectSummonChangeItem(uint32 i)
3027 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3028 return;
3030 Player *player = (Player*)m_caster;
3032 // applied only to using item
3033 if(!m_CastItem)
3034 return;
3036 // ... only to item in own inventory/bank/equip_slot
3037 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3038 return;
3040 uint32 newitemid = m_spellInfo->EffectItemType[i];
3041 if(!newitemid)
3042 return;
3044 uint16 pos = m_CastItem->GetPos();
3046 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3047 if( !pNewItem )
3048 return;
3050 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3052 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3053 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3056 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3058 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3059 player->DurabilityLoss(pNewItem, loosePercent);
3062 if( player->IsInventoryPos( pos ) )
3064 ItemPosCountVec dest;
3065 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3066 if( msg == EQUIP_ERR_OK )
3068 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3070 // prevent crash at access and unexpected charges counting with item update queue corrupt
3071 if(m_CastItem==m_targets.getItemTarget())
3072 m_targets.setItemTarget(NULL);
3074 m_CastItem = NULL;
3076 player->StoreItem( dest, pNewItem, true);
3077 return;
3080 else if( player->IsBankPos ( pos ) )
3082 ItemPosCountVec dest;
3083 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3084 if( msg == EQUIP_ERR_OK )
3086 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3088 // prevent crash at access and unexpected charges counting with item update queue corrupt
3089 if(m_CastItem==m_targets.getItemTarget())
3090 m_targets.setItemTarget(NULL);
3092 m_CastItem = NULL;
3094 player->BankItem( dest, pNewItem, true);
3095 return;
3098 else if( player->IsEquipmentPos ( pos ) )
3100 uint16 dest;
3101 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3102 if( msg == EQUIP_ERR_OK )
3104 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3106 // prevent crash at access and unexpected charges counting with item update queue corrupt
3107 if(m_CastItem==m_targets.getItemTarget())
3108 m_targets.setItemTarget(NULL);
3110 m_CastItem = NULL;
3112 player->EquipItem( dest, pNewItem, true);
3113 player->AutoUnequipOffhandIfNeed();
3114 return;
3118 // fail
3119 delete pNewItem;
3122 void Spell::EffectOpenSecretSafe(uint32 i)
3124 EffectOpenLock(i); //no difference for now
3127 void Spell::EffectProficiency(uint32 /*i*/)
3129 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3130 return;
3131 Player *p_target = (Player*)unitTarget;
3133 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3134 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3136 p_target->AddWeaponProficiency(subClassMask);
3137 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3139 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3141 p_target->AddArmorProficiency(subClassMask);
3142 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3146 void Spell::EffectApplyAreaAura(uint32 i)
3148 if(!unitTarget)
3149 return;
3150 if(!unitTarget->isAlive())
3151 return;
3153 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3154 unitTarget->AddAura(Aur);
3157 void Spell::EffectSummonType(uint32 i)
3159 switch(m_spellInfo->EffectMiscValueB[i])
3161 case SUMMON_TYPE_GUARDIAN:
3162 case SUMMON_TYPE_POSESSED:
3163 case SUMMON_TYPE_POSESSED2:
3164 EffectSummonGuardian(i);
3165 break;
3166 case SUMMON_TYPE_WILD:
3167 EffectSummonWild(i);
3168 break;
3169 case SUMMON_TYPE_DEMON:
3170 EffectSummonDemon(i);
3171 break;
3172 case SUMMON_TYPE_SUMMON:
3173 EffectSummon(i);
3174 break;
3175 case SUMMON_TYPE_CRITTER:
3176 case SUMMON_TYPE_CRITTER2:
3177 case SUMMON_TYPE_CRITTER3:
3178 EffectSummonCritter(i);
3179 break;
3180 case SUMMON_TYPE_TOTEM_SLOT1:
3181 case SUMMON_TYPE_TOTEM_SLOT2:
3182 case SUMMON_TYPE_TOTEM_SLOT3:
3183 case SUMMON_TYPE_TOTEM_SLOT4:
3184 case SUMMON_TYPE_TOTEM:
3185 EffectSummonTotem(i);
3186 break;
3187 case SUMMON_TYPE_UNKNOWN1:
3188 case SUMMON_TYPE_UNKNOWN2:
3189 case SUMMON_TYPE_UNKNOWN3:
3190 case SUMMON_TYPE_UNKNOWN4:
3191 case SUMMON_TYPE_UNKNOWN5:
3192 break;
3193 default:
3194 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3195 break;
3199 void Spell::EffectSummon(uint32 i)
3201 if(m_caster->GetPetGUID())
3202 return;
3204 if(!unitTarget)
3205 return;
3206 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3207 if(!pet_entry)
3208 return;
3209 uint32 level = m_caster->getLevel();
3210 Pet* spawnCreature = new Pet(SUMMON_PET);
3212 if(spawnCreature->LoadPetFromDB(m_caster,pet_entry))
3214 // set timer for unsummon
3215 int32 duration = GetSpellDuration(m_spellInfo);
3216 if(duration > 0)
3217 spawnCreature->SetDuration(duration);
3219 return;
3222 Map *map = m_caster->GetMap();
3223 uint32 pet_number = objmgr.GeneratePetNumber();
3224 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
3226 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3227 delete spawnCreature;
3228 return;
3231 // Summon in dest location
3232 float x,y,z;
3233 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3235 x = m_targets.m_destX;
3236 y = m_targets.m_destY;
3237 z = m_targets.m_destZ;
3239 else
3240 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3242 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3244 if(!spawnCreature->IsPositionValid())
3246 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3247 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3248 delete spawnCreature;
3249 return;
3252 // set timer for unsummon
3253 int32 duration = GetSpellDuration(m_spellInfo);
3254 if(duration > 0)
3255 spawnCreature->SetDuration(duration);
3257 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3258 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3259 spawnCreature->setPowerType(POWER_MANA);
3260 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3261 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3262 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3263 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3264 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3265 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3266 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3267 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3268 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3270 spawnCreature->InitStatsForLevel(level);
3272 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3274 spawnCreature->AIM_Initialize();
3275 spawnCreature->InitPetCreateSpells();
3276 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3277 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3279 std::string name = m_caster->GetName();
3280 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3281 spawnCreature->SetName( name );
3283 map->Add((Creature*)spawnCreature);
3285 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3287 m_caster->SetPet(spawnCreature);
3288 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3289 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3290 ((Player*)m_caster)->PetSpellInitialize();
3294 void Spell::EffectLearnSpell(uint32 i)
3296 if(!unitTarget)
3297 return;
3299 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3301 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3302 EffectLearnPetSpell(i);
3304 return;
3307 Player *player = (Player*)unitTarget;
3309 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3310 player->learnSpell(spellToLearn);
3312 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3315 void Spell::EffectDispel(uint32 i)
3317 if(!unitTarget)
3318 return;
3320 // Fill possible dispell list
3321 std::vector <Aura *> dispel_list;
3323 // Create dispel mask by dispel type
3324 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3325 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3326 Unit::AuraMap const& auras = unitTarget->GetAuras();
3327 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3329 Aura *aur = (*itr).second;
3330 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3332 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3334 bool positive = true;
3335 if (!aur->IsPositive())
3336 positive = false;
3337 else
3338 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3340 // do not remove positive auras if friendly target
3341 // negative auras if non-friendly target
3342 if(positive == unitTarget->IsFriendlyTo(m_caster))
3343 continue;
3345 // Add aura to dispel list
3346 dispel_list.push_back(aur);
3349 // Ok if exist some buffs for dispel try dispel it
3350 if (!dispel_list.empty())
3352 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3353 std::list < uint32 > fail_list; // spell_id
3354 int32 list_size = dispel_list.size();
3355 // Dispell N = damage buffs (or while exist buffs for dispel)
3356 for (int32 count=0; count < damage && list_size > 0; ++count)
3358 // Random select buff for dispel
3359 Aura *aur = dispel_list[urand(0, list_size-1)];
3361 SpellEntry const* spellInfo = aur->GetSpellProto();
3362 // Base dispel chance
3363 // TODO: possible chance depend from spell level??
3364 int32 miss_chance = 0;
3365 // Apply dispel mod from aura caster
3366 if (Unit *caster = aur->GetCaster())
3368 if ( Player* modOwner = caster->GetSpellModOwner() )
3369 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3371 // Try dispel
3372 if (roll_chance_i(miss_chance))
3373 fail_list.push_back(aur->GetId());
3374 else
3375 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3376 // Remove buff from list for prevent doubles
3377 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3379 Aura *dispeled = *j;
3380 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3382 j = dispel_list.erase(j);
3383 --list_size;
3385 else
3386 ++j;
3389 // Send success log and really remove auras
3390 if (!success_list.empty())
3392 int32 count = success_list.size();
3393 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3394 data.append(unitTarget->GetPackGUID()); // Victim GUID
3395 data.append(m_caster->GetPackGUID()); // Caster GUID
3396 data << uint32(m_spellInfo->Id); // Dispell spell id
3397 data << uint8(0); // not used
3398 data << uint32(count); // count
3399 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3401 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3402 data << uint32(spellInfo->Id); // Spell Id
3403 data << uint8(0); // 0 - dispeled !=0 cleansed
3404 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3406 m_caster->SendMessageToSet(&data, true);
3408 // On succes dispel
3409 // Devour Magic
3410 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3412 uint32 heal_spell = 0;
3413 switch (m_spellInfo->Id)
3415 case 19505: heal_spell = 19658; break;
3416 case 19731: heal_spell = 19732; break;
3417 case 19734: heal_spell = 19733; break;
3418 case 19736: heal_spell = 19735; break;
3419 case 27276: heal_spell = 27278; break;
3420 case 27277: heal_spell = 27279; break;
3421 default:
3422 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3423 break;
3425 if (heal_spell)
3426 m_caster->CastSpell(m_caster, heal_spell, true);
3429 // Send fail log to client
3430 if (!fail_list.empty())
3432 // Failed to dispell
3433 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3434 data << uint64(m_caster->GetGUID()); // Caster GUID
3435 data << uint64(unitTarget->GetGUID()); // Victim GUID
3436 data << uint32(m_spellInfo->Id); // Dispell spell id
3437 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3438 data << uint32(*j); // Spell Id
3439 m_caster->SendMessageToSet(&data, true);
3444 void Spell::EffectDualWield(uint32 /*i*/)
3446 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3447 ((Player*)unitTarget)->SetCanDualWield(true);
3450 void Spell::EffectPull(uint32 /*i*/)
3452 // TODO: create a proper pull towards distract spell center for distract
3453 sLog.outDebug("WORLD: Spell Effect DUMMY");
3456 void Spell::EffectDistract(uint32 /*i*/)
3458 // Check for possible target
3459 if (!unitTarget || unitTarget->isInCombat())
3460 return;
3462 // target must be OK to do this
3463 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3464 return;
3466 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3468 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3470 // For players just turn them
3471 WorldPacket data;
3472 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3473 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3474 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3476 else
3478 // Set creature Distracted, Stop it, And turn it
3479 unitTarget->SetOrientation(angle);
3480 unitTarget->StopMoving();
3481 unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3485 void Spell::EffectPickPocket(uint32 /*i*/)
3487 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3488 return;
3490 // victim must be creature and attackable
3491 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3492 return;
3494 // victim have to be alive and humanoid or undead
3495 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3497 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3499 if (chance > irand(0, 19))
3501 // Stealing successful
3502 //sLog.outDebug("Sending loot from pickpocket");
3503 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3505 else
3507 // Reveal action + get attack
3508 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3509 if (((Creature*)unitTarget)->AI())
3510 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3515 void Spell::EffectAddFarsight(uint32 i)
3517 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3518 int32 duration = GetSpellDuration(m_spellInfo);
3519 DynamicObject* dynObj = new DynamicObject;
3520 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3522 delete dynObj;
3523 return;
3525 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3526 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3527 m_caster->AddDynObject(dynObj);
3528 dynObj->GetMap()->Add(dynObj);
3529 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3530 ((Player*)m_caster)->SetFarSight(dynObj->GetGUID());
3533 void Spell::EffectSummonWild(uint32 i)
3535 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3536 if(!creature_entry)
3537 return;
3539 uint32 level = m_caster->getLevel();
3541 // level of creature summoned using engineering item based at engineering skill level
3542 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3544 ItemPrototype const *proto = m_CastItem->GetProto();
3545 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3547 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3548 if(skill202)
3550 level = skill202/5;
3555 // select center of summon position
3556 float center_x = m_targets.m_destX;
3557 float center_y = m_targets.m_destY;
3558 float center_z = m_targets.m_destZ;
3560 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3562 int32 amount = damage > 0 ? damage : 1;
3564 for(int32 count = 0; count < amount; ++count)
3566 float px, py, pz;
3567 // If dest location if present
3568 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3570 // Summon 1 unit in dest location
3571 if (count == 0)
3573 px = m_targets.m_destX;
3574 py = m_targets.m_destY;
3575 pz = m_targets.m_destZ;
3577 // Summon in random point all other units if location present
3578 else
3579 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3581 // Summon if dest location not present near caster
3582 else
3583 m_caster->GetClosePoint(px,py,pz,3.0f);
3585 int32 duration = GetSpellDuration(m_spellInfo);
3587 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3589 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3593 void Spell::EffectSummonGuardian(uint32 i)
3595 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3596 if(!pet_entry)
3597 return;
3599 // Jewelery statue case (totem like)
3600 if(m_spellInfo->SpellIconID==2056)
3602 EffectSummonTotem(i);
3603 return;
3606 // set timer for unsummon
3607 int32 duration = GetSpellDuration(m_spellInfo);
3609 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3610 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3611 // so this code hack in fact
3612 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3613 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3614 return; // find old guardian, ignore summon
3616 // in another case summon new
3617 uint32 level = m_caster->getLevel();
3619 // level of pet summoned using engineering item based at engineering skill level
3620 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3622 ItemPrototype const *proto = m_CastItem->GetProto();
3623 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3625 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3626 if(skill202)
3628 level = skill202/5;
3633 // select center of summon position
3634 float center_x = m_targets.m_destX;
3635 float center_y = m_targets.m_destY;
3636 float center_z = m_targets.m_destZ;
3638 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3640 int32 amount = damage > 0 ? damage : 1;
3642 for(int32 count = 0; count < amount; ++count)
3644 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3646 Map *map = m_caster->GetMap();
3647 uint32 pet_number = objmgr.GeneratePetNumber();
3648 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3650 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3651 delete spawnCreature;
3652 return;
3655 float px, py, pz;
3656 // If dest location if present
3657 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3659 // Summon 1 unit in dest location
3660 if (count == 0)
3662 px = m_targets.m_destX;
3663 py = m_targets.m_destY;
3664 pz = m_targets.m_destZ;
3666 // Summon in random point all other units if location present
3667 else
3668 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3670 // Summon if dest location not present near caster
3671 else
3672 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3674 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3676 if(!spawnCreature->IsPositionValid())
3678 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3679 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3680 delete spawnCreature;
3681 return;
3684 if(duration > 0)
3685 spawnCreature->SetDuration(duration);
3687 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3688 spawnCreature->setPowerType(POWER_MANA);
3689 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3690 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3691 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3692 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3693 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3694 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3695 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3697 spawnCreature->InitStatsForLevel(level);
3698 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3700 spawnCreature->AIM_Initialize();
3702 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3703 ((Player*)m_caster)->AddGuardian(spawnCreature);
3705 map->Add((Creature*)spawnCreature);
3709 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3711 if(!unitTarget)
3712 return;
3714 if(unitTarget->isInFlight())
3715 return;
3717 uint32 mapid = m_caster->GetMapId();
3718 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3720 float fx,fy,fz;
3721 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3723 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3724 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3725 else
3726 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3729 void Spell::EffectLearnSkill(uint32 i)
3731 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3732 return;
3734 if(damage < 0)
3735 return;
3737 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3738 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3739 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3742 void Spell::EffectAddHonor(uint32 /*i*/)
3744 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3745 return;
3747 sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3749 // TODO: find formula for honor reward based on player's level!
3751 // now fixed only for level 70 players:
3752 if (((Player*)unitTarget)->getLevel() == 70)
3753 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3756 void Spell::EffectTradeSkill(uint32 /*i*/)
3758 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3759 return;
3760 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3761 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3762 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3765 void Spell::EffectEnchantItemPerm(uint32 i)
3767 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3768 return;
3769 if (!itemTarget)
3770 return;
3772 Player* p_caster = (Player*)m_caster;
3774 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3776 if (m_spellInfo->EffectMiscValue[i])
3778 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3780 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3781 if(!pEnchant)
3782 return;
3784 // item can be in trade slot and have owner diff. from caster
3785 Player* item_owner = itemTarget->GetOwner();
3786 if(!item_owner)
3787 return;
3789 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3791 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3792 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3793 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3794 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3797 // remove old enchanting before applying new if equipped
3798 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3800 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3802 // add new enchanting if equipped
3803 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3807 void Spell::EffectEnchantItemTmp(uint32 i)
3809 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3810 return;
3812 Player* p_caster = (Player*)m_caster;
3814 if(!itemTarget)
3815 return;
3817 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3819 // Shaman Rockbiter Weapon
3820 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3822 int32 enchnting_damage = m_currentBasePoints[1]+1;
3824 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3825 // with already applied percent bonus from Elemental Weapons talent
3826 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3827 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3828 switch(enchnting_damage)
3830 // Rank 1
3831 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3832 // Rank 2
3833 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3834 case 5: enchant_id = 3025; break; // 20%
3835 // Rank 3
3836 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3837 case 7: enchant_id = 3027; break; // 20%
3838 // Rank 4
3839 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3840 case 10: enchant_id = 503; break; // 14%
3841 case 11: enchant_id = 3031; break; // 20%
3842 // Rank 5
3843 case 15: enchant_id = 3035; break; // 0%
3844 case 16: enchant_id = 1663; break; // 7%
3845 case 17: enchant_id = 3033; break; // 14%
3846 case 18: enchant_id = 3034; break; // 20%
3847 // Rank 6
3848 case 28: enchant_id = 3038; break; // 0%
3849 case 29: enchant_id = 683; break; // 7%
3850 case 31: enchant_id = 3036; break; // 14%
3851 case 33: enchant_id = 3037; break; // 20%
3852 // Rank 7
3853 case 40: enchant_id = 3041; break; // 0%
3854 case 42: enchant_id = 1664; break; // 7%
3855 case 45: enchant_id = 3039; break; // 14%
3856 case 48: enchant_id = 3040; break; // 20%
3857 // Rank 8
3858 case 49: enchant_id = 3044; break; // 0%
3859 case 52: enchant_id = 2632; break; // 7%
3860 case 55: enchant_id = 3042; break; // 14%
3861 case 58: enchant_id = 3043; break; // 20%
3862 // Rank 9
3863 case 62: enchant_id = 2633; break; // 0%
3864 case 66: enchant_id = 3018; break; // 7%
3865 case 70: enchant_id = 3019; break; // 14%
3866 case 74: enchant_id = 3020; break; // 20%
3867 default:
3868 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3869 return;
3873 if (!enchant_id)
3875 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3876 return;
3879 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3880 if(!pEnchant)
3882 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3883 return;
3886 // select enchantment duration
3887 uint32 duration;
3889 // rogue family enchantments exception by duration
3890 if(m_spellInfo->Id==38615)
3891 duration = 1800; // 30 mins
3892 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3893 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3894 duration = 3600; // 1 hour
3895 // shaman family enchantments
3896 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3897 duration = 1800; // 30 mins
3898 // other cases with this SpellVisual already selected
3899 else if(m_spellInfo->SpellVisual[0]==215)
3900 duration = 1800; // 30 mins
3901 // some fishing pole bonuses
3902 else if(m_spellInfo->SpellVisual[0]==563)
3903 duration = 600; // 10 mins
3904 // shaman rockbiter enchantments
3905 else if(m_spellInfo->SpellVisual[0]==0)
3906 duration = 1800; // 30 mins
3907 else if(m_spellInfo->Id==29702)
3908 duration = 300; // 5 mins
3909 else if(m_spellInfo->Id==37360)
3910 duration = 300; // 5 mins
3911 // default case
3912 else
3913 duration = 3600; // 1 hour
3915 // item can be in trade slot and have owner diff. from caster
3916 Player* item_owner = itemTarget->GetOwner();
3917 if(!item_owner)
3918 return;
3920 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3922 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3923 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3924 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3925 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3928 // remove old enchanting before applying new if equipped
3929 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3931 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3933 // add new enchanting if equipped
3934 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3937 void Spell::EffectTameCreature(uint32 /*i*/)
3939 if(m_caster->GetPetGUID())
3940 return;
3942 if(!unitTarget)
3943 return;
3945 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3946 return;
3948 Creature* creatureTarget = (Creature*)unitTarget;
3950 if(creatureTarget->isPet())
3951 return;
3953 if(m_caster->getClass() != CLASS_HUNTER)
3954 return;
3956 // cast finish successfully
3957 //SendChannelUpdate(0);
3958 finish();
3960 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
3962 // kill original creature
3963 creatureTarget->setDeathState(JUST_DIED);
3964 creatureTarget->RemoveCorpse();
3965 creatureTarget->SetHealth(0); // just for nice GM-mode view
3967 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
3969 // prepare visual effect for levelup
3970 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
3972 // add to world
3973 pet->GetMap()->Add((Creature*)pet);
3975 // visual effect for levelup
3976 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
3978 // caster have pet now
3979 m_caster->SetPet(pet);
3981 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3983 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3984 ((Player*)m_caster)->PetSpellInitialize();
3988 void Spell::EffectSummonPet(uint32 i)
3990 uint32 petentry = m_spellInfo->EffectMiscValue[i];
3992 Pet *OldSummon = m_caster->GetPet();
3994 // if pet requested type already exist
3995 if( OldSummon )
3997 if(petentry == 0 || OldSummon->GetEntry() == petentry)
3999 // pet in corpse state can't be summoned
4000 if( OldSummon->isDead() )
4001 return;
4003 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4004 OldSummon->SetMapId(m_caster->GetMapId());
4006 float px, py, pz;
4007 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4009 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4010 m_caster->GetMap()->Add((Creature*)OldSummon);
4012 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4014 ((Player*)m_caster)->PetSpellInitialize();
4016 return;
4019 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4020 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4021 else
4022 return;
4025 Pet* NewSummon = new Pet;
4027 // petentry==0 for hunter "call pet" (current pet summoned if any)
4028 if(NewSummon->LoadPetFromDB(m_caster,petentry))
4030 if(NewSummon->getPetType()==SUMMON_PET)
4032 // Remove Demonic Sacrifice auras (known pet)
4033 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4034 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4036 if((*itr)->GetModifier()->m_miscvalue==2228)
4038 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4039 itr = auraClassScripts.begin();
4041 else
4042 ++itr;
4046 return;
4049 // not error in case fail hunter call pet
4050 if(!petentry)
4052 delete NewSummon;
4053 return;
4056 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4058 if(!cInfo)
4060 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4061 delete NewSummon;
4062 return;
4065 Map *map = m_caster->GetMap();
4066 uint32 pet_number = objmgr.GeneratePetNumber();
4067 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4069 delete NewSummon;
4070 return;
4073 float px, py, pz;
4074 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4076 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4078 if(!NewSummon->IsPositionValid())
4080 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4081 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4082 delete NewSummon;
4083 return;
4086 uint32 petlevel = m_caster->getLevel();
4087 NewSummon->setPetType(SUMMON_PET);
4089 uint32 faction = m_caster->getFaction();
4090 if(m_caster->GetTypeId() == TYPEID_UNIT)
4092 if ( ((Creature*)m_caster)->isTotem() )
4093 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4094 else
4095 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4098 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4099 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4100 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4101 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4102 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4103 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4104 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4105 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4106 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4107 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4109 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4110 // this enables pet details window (Shift+P)
4112 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4113 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4115 NewSummon->InitStatsForLevel(petlevel);
4116 NewSummon->InitPetCreateSpells();
4118 if(NewSummon->getPetType()==SUMMON_PET)
4120 // Remove Demonic Sacrifice auras (new pet)
4121 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4122 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4124 if((*itr)->GetModifier()->m_miscvalue==2228)
4126 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4127 itr = auraClassScripts.begin();
4129 else
4130 ++itr;
4133 // generate new name for summon pet
4134 std::string new_name=objmgr.GeneratePetName(petentry);
4135 if(!new_name.empty())
4136 NewSummon->SetName(new_name);
4138 else if(NewSummon->getPetType()==HUNTER_PET)
4139 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4141 NewSummon->AIM_Initialize();
4142 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4143 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4145 map->Add((Creature*)NewSummon);
4147 m_caster->SetPet(NewSummon);
4148 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4150 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4152 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4153 ((Player*)m_caster)->PetSpellInitialize();
4157 void Spell::EffectLearnPetSpell(uint32 i)
4159 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4160 return;
4162 Player *_player = (Player*)m_caster;
4164 Pet *pet = _player->GetPet();
4165 if(!pet)
4166 return;
4167 if(!pet->isAlive())
4168 return;
4170 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4171 if(!learn_spellproto)
4172 return;
4174 pet->learnSpell(learn_spellproto->Id);
4176 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4177 _player->PetSpellInitialize();
4180 void Spell::EffectTaunt(uint32 /*i*/)
4182 // this effect use before aura Taunt apply for prevent taunt already attacking target
4183 // for spell as marked "non effective at already attacking target"
4184 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4186 if(unitTarget->getVictim()==m_caster)
4188 SendCastResult(SPELL_FAILED_DONT_REPORT);
4189 return;
4193 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4194 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4195 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4198 void Spell::EffectWeaponDmg(uint32 i)
4200 if(!unitTarget)
4201 return;
4202 if(!unitTarget->isAlive())
4203 return;
4205 // multiple weapon dmg effect workaround
4206 // execute only the last weapon damage
4207 // and handle all effects at once
4208 for (int j = 0; j < 3; j++)
4210 switch(m_spellInfo->Effect[j])
4212 case SPELL_EFFECT_WEAPON_DAMAGE:
4213 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4214 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4215 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4216 if (j < i) // we must calculate only at last weapon effect
4217 return;
4218 break;
4222 // some spell specific modifiers
4223 bool customBonusDamagePercentMod = false;
4224 float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4225 float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4226 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4227 bool normalized = false;
4229 int32 spell_bonus = 0; // bonus specific for spell
4230 switch(m_spellInfo->SpellFamilyName)
4232 case SPELLFAMILY_WARRIOR:
4234 // Whirlwind, single only spell with 2 weapon white damage apply if have
4235 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4237 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4238 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4240 // Devastate bonus and sunder armor refresh
4241 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4243 customBonusDamagePercentMod = true;
4244 bonusDamagePercentMod = 0.0f; // only applied if auras found
4246 Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4247 for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4249 SpellEntry const *proto = (*itr)->GetSpellProto();
4250 if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565)
4252 int32 duration = GetSpellDuration(proto);
4253 (*itr)->SetAuraDuration(duration);
4254 (*itr)->SendAuraUpdate(false);
4255 bonusDamagePercentMod += 1.0f; // +100%
4259 break;
4261 case SPELLFAMILY_ROGUE:
4263 // Ambush
4264 if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4266 customBonusDamagePercentMod = true;
4267 bonusDamagePercentMod = 2.5f; // 250%
4269 // Mutilate (for each hand)
4270 else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4272 bool found = false;
4273 // fast check
4274 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4275 found = true;
4276 // full aura scan
4277 else
4279 Unit::AuraMap const& auras = unitTarget->GetAuras();
4280 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4282 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4284 found = true;
4285 break;
4290 if(found)
4291 totalDamagePercentMod *= 1.5f; // 150% if poisoned
4293 break;
4295 case SPELLFAMILY_PALADIN:
4297 // Seal of Command - receive benefit from Spell Damage and Healing
4298 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4300 spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4301 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4303 break;
4305 case SPELLFAMILY_SHAMAN:
4307 // Skyshatter Harness item set bonus
4308 // Stormstrike
4309 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4311 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4312 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4314 // Stormstrike AP Buff
4315 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4317 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4318 break;
4325 int32 fixed_bonus = 0;
4326 for (int j = 0; j < 3; j++)
4328 switch(m_spellInfo->Effect[j])
4330 case SPELL_EFFECT_WEAPON_DAMAGE:
4331 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4332 fixed_bonus += CalculateDamage(j,unitTarget);
4333 break;
4334 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4335 fixed_bonus += CalculateDamage(j,unitTarget);
4336 normalized = true;
4337 break;
4338 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4339 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4341 // applied only to prev.effects fixed damage
4342 if(customBonusDamagePercentMod)
4343 fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4344 else
4345 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4346 break;
4347 default:
4348 break; // not weapon damage effect, just skip
4352 // non-weapon damage
4353 int32 bonus = spell_bonus + fixed_bonus;
4355 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4356 if(bonus)
4358 UnitMods unitMod;
4359 switch(m_attackType)
4361 default:
4362 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4363 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4364 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4367 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4368 bonus = int32(bonus*weapon_total_pct);
4371 // + weapon damage with applied weapon% dmg to base weapon damage in call
4372 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4374 // total damage
4375 bonus = int32(bonus*totalDamagePercentMod);
4377 // prevent negative damage
4378 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4380 const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4382 uint32 hitInfo = 0;
4383 VictimState victimState = VICTIMSTATE_NORMAL;
4384 uint32 blocked_dmg = 0;
4385 uint32 absorbed_dmg = 0;
4386 uint32 resisted_dmg = 0;
4387 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4389 m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4391 if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK) // not send ranged miss/etc
4392 m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4394 bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4395 m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4397 if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4399 eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4401 else
4403 cleanDamage.damage += eff_damage;
4404 eff_damage = 0;
4407 // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4408 m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4410 // Hemorrhage
4411 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4413 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4414 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4417 // Mangle (Cat): CP
4418 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4420 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4421 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4424 // take ammo
4425 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4427 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4429 // wands don't have ammo
4430 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4431 return;
4433 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4435 if(pItem->GetMaxStackCount()==1)
4437 // decrease durability for non-stackable throw weapon
4438 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4440 else
4442 // decrease items amount for stackable throw weapon
4443 uint32 count = 1;
4444 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4447 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4448 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4452 void Spell::EffectThreat(uint32 /*i*/)
4454 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4455 return;
4457 if(!unitTarget->CanHaveThreatList())
4458 return;
4460 unitTarget->AddThreat(m_caster, float(damage));
4463 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4465 if(!unitTarget)
4466 return;
4467 if(!unitTarget->isAlive())
4468 return;
4470 uint32 heal = m_caster->GetMaxHealth();
4472 int32 gain = unitTarget->ModifyHealth(heal);
4473 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4475 m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4478 void Spell::EffectInterruptCast(uint32 /*i*/)
4480 if(!unitTarget)
4481 return;
4482 if(!unitTarget->isAlive())
4483 return;
4485 // TODO: not all spells that used this effect apply cooldown at school spells
4486 // also exist case: apply cooldown to interrupted cast only and to all spells
4487 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4489 if (unitTarget->m_currentSpells[i])
4491 // check if we can interrupt spell
4492 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4494 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4495 unitTarget->InterruptSpell(i,false);
4501 void Spell::EffectSummonObjectWild(uint32 i)
4503 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4505 GameObject* pGameObj = new GameObject;
4507 WorldObject* target = focusObject;
4508 if( !target )
4509 target = m_caster;
4511 float x,y,z;
4512 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4514 x = m_targets.m_destX;
4515 y = m_targets.m_destY;
4516 z = m_targets.m_destZ;
4518 else
4519 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4521 Map *map = target->GetMap();
4523 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4524 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4526 delete pGameObj;
4527 return;
4530 int32 duration = GetSpellDuration(m_spellInfo);
4531 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4532 pGameObj->SetSpellId(m_spellInfo->Id);
4534 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4535 m_caster->AddGameObject(pGameObj);
4536 map->Add(pGameObj);
4538 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4540 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4542 Player *pl = (Player*)m_caster;
4543 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4544 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4546 uint32 team = ALLIANCE;
4548 if(pl->GetTeam() == team)
4549 team = HORDE;
4551 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4556 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4558 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4560 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4561 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4563 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4568 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4570 GameObject* linkedGO = new GameObject;
4571 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4572 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4574 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4575 linkedGO->SetSpellId(m_spellInfo->Id);
4577 m_caster->AddGameObject(linkedGO);
4578 map->Add(linkedGO);
4580 else
4582 delete linkedGO;
4583 linkedGO = NULL;
4584 return;
4589 void Spell::EffectScriptEffect(uint32 effIndex)
4591 // TODO: we must implement hunter pet summon at login there (spell 6962)
4593 // by spell id
4594 switch(m_spellInfo->Id)
4596 // PX-238 Winter Wondervolt TRAP
4597 case 26275:
4599 if( unitTarget->HasAura(26272,0)
4600 || unitTarget->HasAura(26157,0)
4601 || unitTarget->HasAura(26273,0)
4602 || unitTarget->HasAura(26274,0))
4603 return;
4605 uint32 iTmpSpellId;
4607 switch(urand(0,3))
4609 case 0:
4610 iTmpSpellId = 26272;
4611 break;
4612 case 1:
4613 iTmpSpellId = 26157;
4614 break;
4615 case 2:
4616 iTmpSpellId = 26273;
4617 break;
4618 case 3:
4619 iTmpSpellId = 26274;
4620 break;
4623 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4625 return;
4628 // Bending Shinbone
4629 case 8856:
4631 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4632 return;
4634 uint32 spell_id = 0;
4635 switch(urand(1,5))
4637 case 1: spell_id = 8854; break;
4638 default: spell_id = 8855; break;
4641 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4642 return;
4645 // Healthstone creating spells
4646 case 6201:
4647 case 6202:
4648 case 5699:
4649 case 11729:
4650 case 11730:
4651 case 27230:
4653 uint32 itemtype;
4654 uint32 rank = 0;
4655 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4656 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4658 if((*i)->GetId() == 18692)
4660 rank = 1;
4661 break;
4663 else if((*i)->GetId() == 18693)
4665 rank = 2;
4666 break;
4670 static uint32 const itypes[6][3] = {
4671 { 5512,19004,19005}, // Minor Healthstone
4672 { 5511,19006,19007}, // Lesser Healthstone
4673 { 5509,19008,19009}, // Healthstone
4674 { 5510,19010,19011}, // Greater Healthstone
4675 { 9421,19012,19013}, // Major Healthstone
4676 {22103,22104,22105} // Master Healthstone
4679 switch(m_spellInfo->Id)
4681 case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4682 case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4683 case 5699: itemtype=itypes[2][rank];break; // Healthstone
4684 case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4685 case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4686 case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4687 default:
4688 return;
4690 DoCreateItem( effIndex, itemtype );
4691 return;
4693 // Brittle Armor - need remove one 24575 Brittle Armor aura
4694 case 24590:
4695 unitTarget->RemoveSingleAuraFromStack(24575, 0);
4696 unitTarget->RemoveSingleAuraFromStack(24575, 1);
4697 return;
4698 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4699 case 26465:
4700 unitTarget->RemoveSingleAuraFromStack(26464, 0);
4701 return;
4702 // Orb teleport spells
4703 case 25140:
4704 case 25143:
4705 case 25650:
4706 case 25652:
4707 case 29128:
4708 case 29129:
4709 case 35376:
4710 case 35727:
4712 if(!unitTarget)
4713 return;
4715 uint32 spellid;
4716 switch(m_spellInfo->Id)
4718 case 25140: spellid = 32571; break;
4719 case 25143: spellid = 32572; break;
4720 case 25650: spellid = 30140; break;
4721 case 25652: spellid = 30141; break;
4722 case 29128: spellid = 32568; break;
4723 case 29129: spellid = 32569; break;
4724 case 35376: spellid = 25649; break;
4725 case 35727: spellid = 35730; break;
4726 default:
4727 return;
4730 unitTarget->CastSpell(unitTarget,spellid,false);
4731 return;
4734 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4735 case 22539:
4736 case 22972:
4737 case 22975:
4738 case 22976:
4739 case 22977:
4740 case 22978:
4741 case 22979:
4742 case 22980:
4743 case 22981:
4744 case 22982:
4745 case 22983:
4746 case 22984:
4747 case 22985:
4749 if(!unitTarget || !unitTarget->isAlive())
4750 return;
4752 // Onyxia Scale Cloak
4753 if(unitTarget->GetDummyAura(22683))
4754 return;
4756 // Shadow Flame
4757 m_caster->CastSpell(unitTarget, 22682, true);
4758 return;
4760 break;
4762 // Summon Black Qiraji Battle Tank
4763 case 26656:
4765 if(!unitTarget)
4766 return;
4768 // Prevent stacking of mounts
4769 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4771 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4772 if (unitTarget->GetAreaId() == 3428)
4773 unitTarget->CastSpell(unitTarget, 25863, false);
4774 else
4775 unitTarget->CastSpell(unitTarget, 26655, false);
4776 break;
4778 // Piccolo of the Flaming Fire
4779 case 17512:
4781 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4782 return;
4783 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4784 break;
4787 // Dreaming Glory
4788 case 28698:
4790 if(!unitTarget)
4791 return;
4792 unitTarget->CastSpell(unitTarget, 28694, true);
4793 break;
4796 // Netherbloom
4797 case 28702:
4799 if(!unitTarget)
4800 return;
4801 // 25% chance of casting a random buff
4802 if(roll_chance_i(75))
4803 return;
4805 // triggered spells are 28703 to 28707
4806 // Note: some sources say, that there was the possibility of
4807 // receiving a debuff. However, this seems to be removed by a patch.
4808 const uint32 spellid = 28703;
4810 // don't overwrite an existing aura
4811 for(uint8 i=0; i<5; i++)
4812 if(unitTarget->HasAura(spellid+i, 0))
4813 return;
4814 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4815 break;
4818 // Nightmare Vine
4819 case 28720:
4821 if(!unitTarget)
4822 return;
4823 // 25% chance of casting Nightmare Pollen
4824 if(roll_chance_i(75))
4825 return;
4826 unitTarget->CastSpell(unitTarget, 28721, true);
4827 break;
4830 // Mirren's Drinking Hat
4831 case 29830:
4833 uint32 item = 0;
4834 switch ( urand(1,6) )
4836 case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4837 case 4: case 5: item = 23585; break;// Stouthammer Lite
4838 case 6: item = 23586; break;// Aerie Peak Pale Ale
4840 if (item)
4841 DoCreateItem(effIndex,item);
4842 break;
4844 // Improved Sprint
4845 case 30918:
4847 // Removes snares and roots.
4848 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4849 Unit::AuraMap& Auras = unitTarget->GetAuras();
4850 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4852 next = iter;
4853 ++next;
4854 Aura *aur = iter->second;
4855 if (!aur->IsPositive()) //only remove negative spells
4857 // check for mechanic mask
4858 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4860 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4861 if(Auras.empty())
4862 break;
4863 else
4864 next = Auras.begin();
4868 break;
4870 case 41126: // Flame Crash
4872 if(!unitTarget)
4873 return;
4875 unitTarget->CastSpell(unitTarget, 41131, true);
4876 break;
4878 case 44876: // Force Cast - Portal Effect: Sunwell Isle
4880 if(!unitTarget)
4881 return;
4883 unitTarget->CastSpell(unitTarget, 44870, true);
4884 break;
4887 // Goblin Weather Machine
4888 case 46203:
4890 if(!unitTarget)
4891 return;
4893 uint32 spellId;
4894 switch(rand()%4)
4896 case 0:
4897 spellId=46740;
4898 break;
4899 case 1:
4900 spellId=46739;
4901 break;
4902 case 2:
4903 spellId=46738;
4904 break;
4905 case 3:
4906 spellId=46736;
4907 break;
4909 unitTarget->CastSpell(unitTarget, spellId, true);
4910 break;
4912 //5,000 Gold
4913 case 46642:
4915 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4916 return;
4918 ((Player*)unitTarget)->ModifyMoney(50000000);
4920 break;
4924 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4926 switch(m_spellInfo->SpellFamilyFlags)
4928 // Judgement
4929 case 0x800000:
4931 if(!unitTarget || !unitTarget->isAlive())
4932 return;
4933 uint32 spellId2 = 0;
4935 // all seals have aura dummy
4936 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4937 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4939 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4941 // search seal (all seals have judgement's aura dummy spell id in 2 effect
4942 if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4943 continue;
4945 // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4946 spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4948 if(spellId2 <= 1)
4949 continue;
4951 // found, remove seal
4952 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4954 // Sanctified Judgement
4955 Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4956 for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4958 if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4960 int32 chance = (*i)->GetModifier()->m_amount;
4961 if ( roll_chance_i(chance) )
4963 int32 mana = spellInfo->manaCost;
4964 if ( Player* modOwner = m_caster->GetSpellModOwner() )
4965 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4966 mana = int32(mana* 0.8f);
4967 m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4969 break;
4973 break;
4976 m_caster->CastSpell(unitTarget,spellId2,true);
4977 return;
4982 // normal DB scripted effect
4983 if(!unitTarget)
4984 return;
4986 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4987 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4990 void Spell::EffectSanctuary(uint32 /*i*/)
4992 if(!unitTarget)
4993 return;
4994 //unitTarget->CombatStop();
4996 unitTarget->CombatStop();
4997 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
4998 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4999 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5001 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5005 void Spell::EffectAddComboPoints(uint32 /*i*/)
5007 if(!unitTarget)
5008 return;
5010 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5011 return;
5013 if(damage <= 0)
5014 return;
5016 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5019 void Spell::EffectDuel(uint32 i)
5021 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5022 return;
5024 Player *caster = (Player*)m_caster;
5025 Player *target = (Player*)unitTarget;
5027 // caster or target already have requested duel
5028 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5029 return;
5031 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5032 // Don't have to check the target's map since you cannot challenge someone across maps
5033 uint32 mapid = caster->GetMapId();
5034 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5036 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5037 return;
5040 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5041 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5043 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5044 return;
5047 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5048 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5050 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5051 return;
5054 //CREATE DUEL FLAG OBJECT
5055 GameObject* pGameObj = new GameObject;
5057 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5059 Map *map = m_caster->GetMap();
5060 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5061 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5062 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5063 m_caster->GetPositionZ(),
5064 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5066 delete pGameObj;
5067 return;
5070 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5071 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5072 int32 duration = GetSpellDuration(m_spellInfo);
5073 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5074 pGameObj->SetSpellId(m_spellInfo->Id);
5076 m_caster->AddGameObject(pGameObj);
5077 map->Add(pGameObj);
5078 //END
5080 // Send request
5081 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5082 data << pGameObj->GetGUID();
5083 data << caster->GetGUID();
5084 caster->GetSession()->SendPacket(&data);
5085 target->GetSession()->SendPacket(&data);
5087 // create duel-info
5088 DuelInfo *duel = new DuelInfo;
5089 duel->initiator = caster;
5090 duel->opponent = target;
5091 duel->startTime = 0;
5092 duel->startTimer = 0;
5093 caster->duel = duel;
5095 DuelInfo *duel2 = new DuelInfo;
5096 duel2->initiator = caster;
5097 duel2->opponent = caster;
5098 duel2->startTime = 0;
5099 duel2->startTimer = 0;
5100 target->duel = duel2;
5102 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5103 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5106 void Spell::EffectStuck(uint32 /*i*/)
5108 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5109 return;
5111 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5112 return;
5114 Player* pTarget = (Player*)unitTarget;
5116 sLog.outDebug("Spell Effect: Stuck");
5117 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());
5119 if(pTarget->isInFlight())
5120 return;
5122 // homebind location is loaded always
5123 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5125 // Stuck spell trigger Hearthstone cooldown
5126 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5127 if(!spellInfo)
5128 return;
5129 Spell spell(pTarget,spellInfo,true,0);
5130 spell.SendSpellCooldown();
5133 void Spell::EffectSummonPlayer(uint32 /*i*/)
5135 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5136 return;
5138 // Evil Twin (ignore player summon, but hide this for summoner)
5139 if(unitTarget->GetDummyAura(23445))
5140 return;
5142 float x,y,z;
5143 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5145 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5147 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5148 data << uint64(m_caster->GetGUID()); // summoner guid
5149 data << uint32(m_caster->GetZoneId()); // summoner zone
5150 data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs
5151 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5154 static ScriptInfo generateActivateCommand()
5156 ScriptInfo si;
5157 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5158 return si;
5161 void Spell::EffectActivateObject(uint32 effect_idx)
5163 if(!gameObjTarget)
5164 return;
5166 static ScriptInfo activateCommand = generateActivateCommand();
5168 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5170 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5173 void Spell::EffectApplyGlyph(uint32 i)
5175 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5176 return;
5178 Player *player = (Player*)m_caster;
5180 // remove old glyph
5181 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5183 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5185 player->RemoveAurasDueToSpell(old_gp->SpellId);
5186 player->SetGlyph(m_glyphIndex, 0);
5190 // apply new one
5191 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5193 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5195 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5197 if(gp->TypeFlags != gs->TypeFlags)
5199 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5200 return; // glyph slot missmatch
5204 player->CastSpell(m_caster, gp->SpellId, true);
5205 player->SetGlyph(m_glyphIndex, glyph);
5206 if(m_CastItem)
5207 player->DestroyItemCount(m_CastItem->GetEntry(), 1, true);
5212 void Spell::EffectSummonTotem(uint32 i)
5214 uint8 slot = 0;
5215 switch(m_spellInfo->EffectMiscValueB[i])
5217 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5218 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5219 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5220 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5221 // Battle standard case
5222 case SUMMON_TYPE_TOTEM: slot = 254; break;
5223 // jewelery statue case, like totem without slot
5224 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5225 default: return;
5228 if(slot < MAX_TOTEM)
5230 uint64 guid = m_caster->m_TotemSlot[slot];
5231 if(guid != 0)
5233 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5234 if(OldTotem && OldTotem->isTotem())
5235 ((Totem*)OldTotem)->UnSummon();
5239 uint32 team = 0;
5240 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5241 team = ((Player*)m_caster)->GetTeam();
5243 Totem* pTotem = new Totem;
5245 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5247 delete pTotem;
5248 return;
5251 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5253 float x,y,z;
5254 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5256 // totem must be at same Z in case swimming caster and etc.
5257 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5258 z = m_caster->GetPositionZ();
5260 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5262 if(slot < MAX_TOTEM)
5263 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5265 pTotem->SetOwner(m_caster->GetGUID());
5266 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5268 int32 duration=GetSpellDuration(m_spellInfo);
5269 if(Player* modOwner = m_caster->GetSpellModOwner())
5270 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5271 pTotem->SetDuration(duration);
5273 if (damage) // if not spell info, DB values used
5275 pTotem->SetMaxHealth(damage);
5276 pTotem->SetHealth(damage);
5279 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5280 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5282 pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5283 pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5285 pTotem->Summon(m_caster);
5287 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5289 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5290 data << uint8(slot);
5291 data << uint64(pTotem->GetGUID());
5292 data << uint32(duration);
5293 data << uint32(m_spellInfo->Id);
5294 ((Player*)m_caster)->SendDirectMessage(&data);
5298 void Spell::EffectEnchantHeldItem(uint32 i)
5300 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5301 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5302 return;
5304 Player* item_owner = (Player*)unitTarget;
5305 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5307 if(!item )
5308 return;
5310 // must be equipped
5311 if(!item ->IsEquipped())
5312 return;
5314 if (m_spellInfo->EffectMiscValue[i])
5316 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5317 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5318 if(!duration)
5319 duration = m_currentBasePoints[i]+1; //Base points after ..
5320 if(!duration)
5321 duration = 10; //10 seconds for enchants which don't have listed duration
5323 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5324 if(!pEnchant)
5325 return;
5327 // Always go to temp enchantment slot
5328 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5330 // Enchantment will not be applied if a different one already exists
5331 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5332 return;
5334 // Apply the temporary enchantment
5335 item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5336 item_owner->ApplyEnchantment(item,slot,true);
5340 void Spell::EffectDisEnchant(uint32 /*i*/)
5342 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5343 return;
5345 Player* p_caster = (Player*)m_caster;
5346 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5347 return;
5349 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5351 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5353 // item will be removed at disenchanting end
5356 void Spell::EffectInebriate(uint32 /*i*/)
5358 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5359 return;
5361 Player *player = (Player*)unitTarget;
5362 uint16 currentDrunk = player->GetDrunkValue();
5363 uint16 drunkMod = damage * 256;
5364 if (currentDrunk + drunkMod > 0xFFFF)
5365 currentDrunk = 0xFFFF;
5366 else
5367 currentDrunk += drunkMod;
5368 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5371 void Spell::EffectFeedPet(uint32 i)
5373 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5374 return;
5376 Player *_player = (Player*)m_caster;
5378 if(!itemTarget)
5379 return;
5381 Pet *pet = _player->GetPet();
5382 if(!pet)
5383 return;
5385 if(!pet->isAlive())
5386 return;
5388 int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5389 if(benefit <= 0)
5390 return;
5392 uint32 count = 1;
5393 _player->DestroyItemCount(itemTarget,count,true);
5394 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5396 m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5399 void Spell::EffectDismissPet(uint32 /*i*/)
5401 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5402 return;
5404 Pet* pet = m_caster->GetPet();
5406 // not let dismiss dead pet
5407 if(!pet||!pet->isAlive())
5408 return;
5410 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5413 void Spell::EffectSummonObject(uint32 i)
5415 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5417 uint8 slot = 0;
5418 switch(m_spellInfo->Effect[i])
5420 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5421 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5422 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5423 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5424 default: return;
5427 uint64 guid = m_caster->m_ObjectSlot[slot];
5428 if(guid != 0)
5430 GameObject* obj = NULL;
5431 if( m_caster )
5432 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5434 if(obj) obj->Delete();
5435 m_caster->m_ObjectSlot[slot] = 0;
5438 GameObject* pGameObj = new GameObject;
5440 float rot2 = sin(m_caster->GetOrientation()/2);
5441 float rot3 = cos(m_caster->GetOrientation()/2);
5443 float x,y,z;
5444 // If dest location if present
5445 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5447 x = m_targets.m_destX;
5448 y = m_targets.m_destY;
5449 z = m_targets.m_destZ;
5451 // Summon in random point all other units if location present
5452 else
5453 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5455 Map *map = m_caster->GetMap();
5456 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5458 delete pGameObj;
5459 return;
5462 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5463 int32 duration = GetSpellDuration(m_spellInfo);
5464 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5465 pGameObj->SetSpellId(m_spellInfo->Id);
5466 m_caster->AddGameObject(pGameObj);
5468 map->Add(pGameObj);
5469 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5470 data << pGameObj->GetGUID();
5471 m_caster->SendMessageToSet(&data,true);
5473 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5476 void Spell::EffectResurrect(uint32 /*effIndex*/)
5478 if(!unitTarget)
5479 return;
5480 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5481 return;
5483 if(unitTarget->isAlive())
5484 return;
5485 if(!unitTarget->IsInWorld())
5486 return;
5488 switch (m_spellInfo->Id)
5490 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5491 case 8342:
5492 if (roll_chance_i(67))
5494 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5495 return;
5497 break;
5498 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5499 case 22999:
5500 if (roll_chance_i(50))
5502 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5503 return;
5505 break;
5506 default:
5507 break;
5510 Player* pTarget = ((Player*)unitTarget);
5512 if(pTarget->isRessurectRequested()) // already have one active request
5513 return;
5515 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5516 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5518 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5519 SendResurrectRequest(pTarget);
5522 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5524 if(!unitTarget || !unitTarget->isAlive())
5525 return;
5527 if( unitTarget->m_extraAttacks )
5528 return;
5530 unitTarget->m_extraAttacks = damage;
5533 void Spell::EffectParry(uint32 /*i*/)
5535 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5536 ((Player*)unitTarget)->SetCanParry(true);
5539 void Spell::EffectBlock(uint32 /*i*/)
5541 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5542 ((Player*)unitTarget)->SetCanBlock(true);
5545 void Spell::EffectMomentMove(uint32 i)
5547 if(unitTarget->isInFlight())
5548 return;
5550 if( m_spellInfo->rangeIndex== 1) //self range
5552 uint32 mapid = m_caster->GetMapId();
5553 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5555 // before caster
5556 float fx,fy,fz;
5557 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5558 float ox,oy,oz;
5559 unitTarget->GetPosition(ox,oy,oz);
5561 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5562 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5564 fx = fx2;
5565 fy = fy2;
5566 fz = fz2;
5567 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5570 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5571 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5572 else
5573 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5577 void Spell::EffectReputation(uint32 i)
5579 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5580 return;
5582 Player *_player = (Player*)unitTarget;
5584 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5586 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5588 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5590 if(!factionEntry)
5591 return;
5593 _player->ModifyFactionReputation(factionEntry,rep_change);
5596 void Spell::EffectQuestComplete(uint32 i)
5598 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5599 return;
5601 Player *_player = (Player*)m_caster;
5603 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5604 _player->AreaExploredOrEventHappens(quest_id);
5607 void Spell::EffectSelfResurrect(uint32 i)
5609 if(!unitTarget || unitTarget->isAlive())
5610 return;
5611 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5612 return;
5613 if(!unitTarget->IsInWorld())
5614 return;
5616 uint32 health = 0;
5617 uint32 mana = 0;
5619 // flat case
5620 if(damage < 0)
5622 health = uint32(-damage);
5623 mana = m_spellInfo->EffectMiscValue[i];
5625 // percent case
5626 else
5628 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5629 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5630 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5633 Player *plr = ((Player*)unitTarget);
5634 plr->ResurrectPlayer(0.0f);
5636 plr->SetHealth( health );
5637 plr->SetPower(POWER_MANA, mana );
5638 plr->SetPower(POWER_RAGE, 0 );
5639 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5641 plr->SpawnCorpseBones();
5643 plr->SaveToDB();
5646 void Spell::EffectSkinning(uint32 /*i*/)
5648 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5649 return;
5650 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5651 return;
5653 Creature* creature = (Creature*) unitTarget;
5654 int32 targetLevel = creature->getLevel();
5656 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5658 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5659 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5661 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5663 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5665 // Double chances for elites
5666 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5669 void Spell::EffectCharge(uint32 /*i*/)
5671 if(!unitTarget || !m_caster)
5672 return;
5674 float x, y, z;
5675 unitTarget->GetContactPoint(m_caster, x, y, z);
5676 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5677 ((Creature *)unitTarget)->StopMoving();
5679 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5680 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5682 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5683 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5685 // not all charge effects used in negative spells
5686 if ( !IsPositiveSpell(m_spellInfo->Id))
5687 m_caster->Attack(unitTarget,true);
5690 void Spell::EffectSummonCritter(uint32 i)
5692 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5693 return;
5694 Player* player = (Player*)m_caster;
5696 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5697 if(!pet_entry)
5698 return;
5700 Pet* old_critter = player->GetMiniPet();
5702 // for same pet just despawn
5703 if(old_critter && old_critter->GetEntry() == pet_entry)
5705 player->RemoveMiniPet();
5706 return;
5709 // despawn old pet before summon new
5710 if(old_critter)
5711 player->RemoveMiniPet();
5713 // summon new pet
5714 Pet* critter = new Pet(MINI_PET);
5716 Map *map = m_caster->GetMap();
5717 uint32 pet_number = objmgr.GeneratePetNumber();
5718 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5719 map, pet_entry, pet_number))
5721 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5722 delete critter;
5723 return;
5726 float x,y,z;
5727 // If dest location if present
5728 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5730 x = m_targets.m_destX;
5731 y = m_targets.m_destY;
5732 z = m_targets.m_destZ;
5734 // Summon if dest location not present near caster
5735 else
5736 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5738 critter->Relocate(x,y,z,m_caster->GetOrientation());
5740 if(!critter->IsPositionValid())
5742 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5743 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5744 delete critter;
5745 return;
5748 critter->SetOwnerGUID(m_caster->GetGUID());
5749 critter->SetCreatorGUID(m_caster->GetGUID());
5750 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5751 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5753 critter->AIM_Initialize();
5754 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5755 critter->SetMaxHealth(1);
5756 critter->SetHealth(1);
5757 critter->SetLevel(1);
5759 // set timer for unsummon
5760 int32 duration = GetSpellDuration(m_spellInfo);
5761 if(duration > 0)
5762 critter->SetDuration(duration);
5764 std::string name = player->GetName();
5765 name.append(petTypeSuffix[critter->getPetType()]);
5766 critter->SetName( name );
5767 player->SetMiniPet(critter);
5769 map->Add((Creature*)critter);
5772 void Spell::EffectKnockBack(uint32 i)
5774 if(!unitTarget || !m_caster)
5775 return;
5777 // Effect only works on players
5778 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5779 return;
5781 float vsin = sin(m_caster->GetAngle(unitTarget));
5782 float vcos = cos(m_caster->GetAngle(unitTarget));
5784 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5785 data.append(unitTarget->GetPackGUID());
5786 data << uint32(0); // Sequence
5787 data << float(vcos); // x direction
5788 data << float(vsin); // y direction
5789 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5790 data << float(damage/-10); // Z Movement speed (vertical)
5792 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5795 void Spell::EffectSendTaxi(uint32 i)
5797 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5798 return;
5800 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5801 if(!entry)
5802 return;
5804 std::vector<uint32> nodes;
5806 nodes.resize(2);
5807 nodes[0] = entry->from;
5808 nodes[1] = entry->to;
5810 uint32 mountid = 0;
5811 switch(m_spellInfo->Id)
5813 case 31606: //Stormcrow Amulet
5814 mountid = 17447;
5815 break;
5816 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5817 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5818 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5819 mountid = 22840;
5820 break;
5821 case 34905: //Stealth Flight
5822 mountid = 6851;
5823 break;
5826 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5830 void Spell::EffectPlayerPull(uint32 i)
5832 if(!unitTarget || !m_caster)
5833 return;
5835 // Effect only works on players
5836 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5837 return;
5839 float vsin = sin(unitTarget->GetAngle(m_caster));
5840 float vcos = cos(unitTarget->GetAngle(m_caster));
5842 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5843 data.append(unitTarget->GetPackGUID());
5844 data << uint32(0); // Sequence
5845 data << float(vcos); // x direction
5846 data << float(vsin); // y direction
5847 // Horizontal speed
5848 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5849 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
5851 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5854 void Spell::EffectDispelMechanic(uint32 i)
5856 if(!unitTarget)
5857 return;
5859 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5861 Unit::AuraMap& Auras = unitTarget->GetAuras();
5862 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5864 next = iter;
5865 ++next;
5866 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5867 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5869 unitTarget->RemoveAurasDueToSpell(spell->Id);
5870 if(Auras.empty())
5871 break;
5872 else
5873 next = Auras.begin();
5876 return;
5879 void Spell::EffectSummonDeadPet(uint32 /*i*/)
5881 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5882 return;
5883 Player *_player = (Player*)m_caster;
5884 Pet *pet = _player->GetPet();
5885 if(!pet)
5886 return;
5887 if(pet->isAlive())
5888 return;
5889 if(damage < 0)
5890 return;
5891 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5892 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5893 pet->setDeathState( ALIVE );
5894 pet->clearUnitState(UNIT_STAT_ALL_STATE);
5895 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5897 pet->AIM_Initialize();
5899 _player->PetSpellInitialize();
5900 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5903 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5905 float mana = 0;
5906 for(int slot = 0; slot < MAX_TOTEM; ++slot)
5908 if(!m_caster->m_TotemSlot[slot])
5909 continue;
5911 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5912 if(totem && totem->isTotem())
5914 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5915 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5916 if(spellInfo)
5917 mana += spellInfo->manaCost * damage / 100;
5918 ((Totem*)totem)->UnSummon();
5922 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5923 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5926 void Spell::EffectDurabilityDamage(uint32 i)
5928 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5929 return;
5931 int32 slot = m_spellInfo->EffectMiscValue[i];
5933 // FIXME: some spells effects have value -1/-2
5934 // Possibly its mean -1 all player equipped items and -2 all items
5935 if(slot < 0)
5937 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5938 return;
5941 // invalid slot value
5942 if(slot >= INVENTORY_SLOT_BAG_END)
5943 return;
5945 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5946 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5949 void Spell::EffectDurabilityDamagePCT(uint32 i)
5951 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5952 return;
5954 int32 slot = m_spellInfo->EffectMiscValue[i];
5956 // FIXME: some spells effects have value -1/-2
5957 // Possibly its mean -1 all player equipped items and -2 all items
5958 if(slot < 0)
5960 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5961 return;
5964 // invalid slot value
5965 if(slot >= INVENTORY_SLOT_BAG_END)
5966 return;
5968 if(damage <= 0)
5969 return;
5971 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5972 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5975 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5977 if(!unitTarget)
5978 return;
5980 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5983 void Spell::EffectTransmitted(uint32 effIndex)
5985 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5987 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5989 if (!goinfo)
5991 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5992 return;
5995 float fx,fy,fz;
5997 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5999 fx = m_targets.m_destX;
6000 fy = m_targets.m_destY;
6001 fz = m_targets.m_destZ;
6003 //FIXME: this can be better check for most objects but still hack
6004 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6006 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6007 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6009 else
6011 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6012 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6013 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6015 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6018 Map *cMap = m_caster->GetMap();
6020 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6022 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6023 { // but this is not proper, we really need to ignore not materialized objects
6024 SendCastResult(SPELL_FAILED_NOT_HERE);
6025 SendChannelUpdate(0);
6026 return;
6029 // replace by water level in this case
6030 fz = cMap->GetWaterLevel(fx,fy);
6032 // if gameobject is summoning object, it should be spawned right on caster's position
6033 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6035 m_caster->GetPosition(fx,fy,fz);
6038 GameObject* pGameObj = new GameObject;
6040 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6041 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6043 delete pGameObj;
6044 return;
6047 int32 duration = GetSpellDuration(m_spellInfo);
6049 switch(goinfo->type)
6051 case GAMEOBJECT_TYPE_FISHINGNODE:
6053 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6054 // Orientation3
6055 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
6056 // Orientation4
6057 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
6058 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6060 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6061 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6062 int32 lastSec;
6063 switch(urand(0, 3))
6065 case 0: lastSec = 3; break;
6066 case 1: lastSec = 7; break;
6067 case 2: lastSec = 13; break;
6068 case 3: lastSec = 17; break;
6071 duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6072 break;
6074 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6076 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6078 pGameObj->AddUniqueUse((Player*)m_caster);
6079 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6081 break;
6083 case GAMEOBJECT_TYPE_FISHINGHOLE:
6084 case GAMEOBJECT_TYPE_CHEST:
6085 default:
6087 break;
6091 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6093 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6095 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6096 pGameObj->SetSpellId(m_spellInfo->Id);
6098 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6099 //m_caster->AddGameObject(pGameObj);
6100 //m_ObjToDel.push_back(pGameObj);
6102 cMap->Add(pGameObj);
6104 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6105 data << uint64(pGameObj->GetGUID());
6106 m_caster->SendMessageToSet(&data,true);
6108 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6110 GameObject* linkedGO = new GameObject;
6111 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6112 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6114 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6115 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6116 linkedGO->SetSpellId(m_spellInfo->Id);
6117 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6119 linkedGO->GetMap()->Add(linkedGO);
6121 else
6123 delete linkedGO;
6124 linkedGO = NULL;
6125 return;
6130 void Spell::EffectProspecting(uint32 /*i*/)
6132 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6133 return;
6135 Player* p_caster = (Player*)m_caster;
6136 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6137 return;
6139 if(itemTarget->GetCount() < 5)
6140 return;
6142 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6144 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6145 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6146 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6149 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6152 void Spell::EffectMilling(uint32 /*i*/)
6154 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6155 return;
6157 Player* p_caster = (Player*)m_caster;
6158 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6159 return;
6161 if(itemTarget->GetCount() < 5)
6162 return;
6164 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6166 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6167 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6168 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6171 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6174 void Spell::EffectSkill(uint32 /*i*/)
6176 sLog.outDebug("WORLD: SkillEFFECT");
6179 void Spell::EffectSummonDemon(uint32 i)
6181 float px = m_targets.m_destX;
6182 float py = m_targets.m_destY;
6183 float pz = m_targets.m_destZ;
6185 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6186 if (!Charmed)
6187 return;
6189 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6190 Charmed->SetLevel(m_caster->getLevel());
6192 // TODO: Add damage/mana/hp according to level
6194 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6196 // Enslave demon effect, without mana cost and cooldown
6197 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6199 // Inferno effect
6200 Charmed->CastSpell(Charmed, 22703, true, 0);
6204 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6205 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6206 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6207 This is why we use a half sec delay between the visual effect and the resurrection itself */
6208 void Spell::EffectSpiritHeal(uint32 /*i*/)
6211 if(!unitTarget || unitTarget->isAlive())
6212 return;
6213 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6214 return;
6215 if(!unitTarget->IsInWorld())
6216 return;
6218 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6219 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6220 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6221 ((Player*)unitTarget)->SpawnCorpseBones();
6225 // remove insignia spell effect
6226 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6228 sLog.outDebug("Effect: SkinPlayerCorpse");
6229 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6230 return;
6232 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6235 void Spell::EffectStealBeneficialBuff(uint32 i)
6237 sLog.outDebug("Effect: StealBeneficialBuff");
6239 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6240 return;
6242 std::vector <Aura *> steal_list;
6243 // Create dispel mask by dispel type
6244 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6245 Unit::AuraMap const& auras = unitTarget->GetAuras();
6246 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6248 Aura *aur = (*itr).second;
6249 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6251 // Need check for passive? this
6252 if (aur->IsPositive() && !aur->IsPassive())
6253 steal_list.push_back(aur);
6256 // Ok if exist some buffs for dispel try dispel it
6257 if (!steal_list.empty())
6259 std::list < std::pair<uint32,uint64> > success_list;
6260 int32 list_size = steal_list.size();
6261 // Dispell N = damage buffs (or while exist buffs for dispel)
6262 for (int32 count=0; count < damage && list_size > 0; ++count)
6264 // Random select buff for dispel
6265 Aura *aur = steal_list[urand(0, list_size-1)];
6266 // Not use chance for steal
6267 // TODO possible need do it
6268 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6270 // Remove buff from list for prevent doubles
6271 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6273 Aura *stealed = *j;
6274 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6276 j = steal_list.erase(j);
6277 --list_size;
6279 else
6280 ++j;
6283 // Really try steal and send log
6284 if (!success_list.empty())
6286 int32 count = success_list.size();
6287 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6288 data.append(unitTarget->GetPackGUID()); // Victim GUID
6289 data.append(m_caster->GetPackGUID()); // Caster GUID
6290 data << uint32(m_spellInfo->Id); // Dispell spell id
6291 data << uint8(0); // not used
6292 data << uint32(count); // count
6293 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6295 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6296 data << uint32(spellInfo->Id); // Spell Id
6297 data << uint8(0); // 0 - steals !=0 transfers
6298 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6300 m_caster->SendMessageToSet(&data, true);
6305 void Spell::EffectKillCredit(uint32 i)
6307 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6308 return;
6310 ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6313 void Spell::EffectQuestFail(uint32 i)
6315 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6316 return;
6318 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6321 void Spell::EffectActivateRune(uint32 i)
6323 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6324 return;
6326 Player *plr = (Player*)m_caster;
6328 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6329 return;
6331 for(uint32 j = 0; j < MAX_RUNES; ++j)
6333 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[i])
6335 plr->SetRuneCooldown(j, 0);
6340 void Spell::EffectTitanGrip(uint32 i)
6342 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6343 ((Player*)unitTarget)->SetCanTitanGrip(true);