2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
24 #include "UpdateMask.h"
26 #include "ObjectMgr.h"
29 #include "SkillExtraItems.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
51 #include "SocialMgr.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.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 from pre-1.2.1
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvironmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectBind
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectUnused
, // 12 SPELL_EFFECT_PORTAL unused from pre-1.2.1, exist 2 spell, but not exist any data about its real usage
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused from pre-1.2.1
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused from pre-1.2.1
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused from pre-1.2.1
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::EffectEmpty
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectEmpty
, // 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::EffectEmpty
, // 25 SPELL_EFFECT_WEAPON spell per weapon type, in ItemSubclassmask store mask that can be used for usability check at equip, but current way using skill also work.
86 &Spell::EffectEmpty
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectEmpty
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectEmpty
, // 39 SPELL_EFFECT_LANGUAGE misc store lang id
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectJump
, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump
, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN spawn/login animation, expected by spawn unit cast, also base points store some dynflags
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 from pre-1.2.1
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT unused from pre-1.2.1
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem
, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectRestoreItemCharges
, // 66 SPELL_EFFECT_RESTORE_ITEM_CHARGES itemtype - is affected item ID
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectNULL
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS one spell: Trainer: Untrain Talents
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectNULL
, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
148 &Spell::EffectNULL
, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
149 &Spell::EffectNULL
, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
150 &Spell::EffectKillCreditPersonal
, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_93 (old 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::EffectSummonAllTotems
, // 97 SPELL_EFFECT_SUMMON_ALL_TOTEMS
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused
, //112 SPELL_EFFECT_112 (old 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::EffectPlayMusic
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack
, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectNULL
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectNULL
, //148 SPELL_EFFECT_148 single spell: Inflicts Fire damage to an enemy.
209 &Spell::EffectCharge2
, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectNULL
, //150 SPELL_EFFECT_150 2 spells in 3.3.2
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::EffectTeachTaxiNode
, //154 SPELL_EFFECT_TEACH_TAXI_NODE single spell: Teach River's Heart Taxi Path
215 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL
, //160 SPELL_EFFECT_160 single spell: Nerub'ar Web Random Unit
221 &Spell::EffectSpecCount
, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectActivateSpec
, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectEmpty(SpellEffectIndex
/*eff_idx*/)
227 // NOT NEED ANY IMPLEMENTATION CODE, EFFECT POSISBLE USED AS MARKER OR CLIENT INFORM
230 void Spell::EffectNULL(SpellEffectIndex
/*eff_idx*/)
232 sLog
.outDebug("WORLD: Spell Effect DUMMY");
235 void Spell::EffectUnused(SpellEffectIndex
/*eff_idx*/)
237 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
240 void Spell::EffectResurrectNew(SpellEffectIndex eff_idx
)
242 if(!unitTarget
|| unitTarget
->isAlive())
245 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
248 if(!unitTarget
->IsInWorld())
251 Player
* pTarget
= ((Player
*)unitTarget
);
253 if(pTarget
->isRessurectRequested()) // already have one active request
256 uint32 health
= damage
;
257 uint32 mana
= m_spellInfo
->EffectMiscValue
[eff_idx
];
258 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
259 SendResurrectRequest(pTarget
);
262 void Spell::EffectInstaKill(SpellEffectIndex
/*eff_idx*/)
264 if( !unitTarget
|| !unitTarget
->isAlive() )
268 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
270 uint32 entry
= unitTarget
->GetEntry();
274 case 416: spellID
=18789; break; //imp
275 case 417: spellID
=18792; break; //fellhunter
276 case 1860: spellID
=18790; break; //void
277 case 1863: spellID
=18791; break; //succubus
278 case 17252: spellID
=35701; break; //fellguard
280 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry
);
284 m_caster
->CastSpell(m_caster
, spellID
, true);
287 if(m_caster
== unitTarget
) // prevent interrupt message
290 m_caster
->DealDamage(unitTarget
, unitTarget
->GetHealth(), NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
293 void Spell::EffectEnvironmentalDMG(SpellEffectIndex eff_idx
)
298 // Note: this hack with damage replace required until GO casting not implemented
299 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
300 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
301 damage
= m_spellInfo
->CalculateSimpleValue(eff_idx
);
303 m_caster
->CalcAbsorbResist(m_caster
, GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
305 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
306 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
307 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
, damage
);
310 void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx
)
312 if( unitTarget
&& unitTarget
->isAlive())
314 switch(m_spellInfo
->SpellFamilyName
)
316 case SPELLFAMILY_GENERIC
:
318 switch(m_spellInfo
->Id
) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
329 case 64422: case 64688: // Sonic Screech
330 case 70492: case 72505: // Ooze Eruption
331 case 71904: // Chaos Bane
332 case 72624: case 72625: // Ooze Eruption
335 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
336 if(ihit
->effectMask
& (1<<effect_idx
))
339 damage
/= count
; // divide to all targets
342 // percent from health with min
343 case 25599: // Thundercrash
345 damage
= unitTarget
->GetHealth() / 2;
350 // Intercept (warrior spell trigger)
354 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
357 // percent max target health
358 case 29142: // Eyesore Blaster
359 case 35139: // Throw Boom's Doom
360 case 49882: // Leviroth Self-Impale
362 damage
= damage
* unitTarget
->GetMaxHealth() / 100;
368 damage
= unitTarget
->GetMaxHealth() / 2;
374 damage
= unitTarget
->GetMaxHealth() / 10;
377 // Hand of Rekoning (name not have typos ;) )
379 damage
+= uint32(0.5f
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
384 case SPELLFAMILY_MAGE
:
385 // remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
386 // NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
387 if ((m_spellInfo
->SchoolMask
& SPELL_SCHOOL_MASK_ARCANE
) && !(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000)))
388 m_caster
->RemoveAurasDueToSpell(36032); // Arcane Blast buff
390 case SPELLFAMILY_WARRIOR
:
393 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x40000000000))
395 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
398 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000020000000000)) && m_spellInfo
->Category
==1209)
399 damage
+= int32(m_caster
->GetShieldBlockValue());
401 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x10000000000))
403 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
404 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
406 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
407 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000400))
408 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
409 // Heroic Throw ${$m1+$AP*.50}
410 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000100000000))
411 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
412 // Shattering Throw ${$m1+$AP*.50}
413 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0040000000000000))
414 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
415 // Shockwave ${$m3/100*$AP}
416 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000800000000000))
418 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, EFFECT_INDEX_2
, m_spellInfo
->EffectBasePoints
[EFFECT_INDEX_2
], unitTarget
);
420 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
424 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000080))
426 damage
+=int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 12 / 100);
430 case SPELLFAMILY_WARLOCK
:
432 // Incinerate Rank 1 & 2
433 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00004000000000)) && m_spellInfo
->SpellIconID
==2128)
435 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
436 // Check aura state for speed but aura state set not only for Immolate spell
437 if(unitTarget
->HasAuraState(AURA_STATE_CONFLAGRATE
))
439 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
440 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
443 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
444 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x00000000000004)))
453 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0001000000000000))
456 switch(m_spellInfo
->Id
)
458 case 47897: m_caster
->CastSpell(unitTarget
, 47960, true); break;
459 case 61290: m_caster
->CastSpell(unitTarget
, 61291, true); break;
461 sLog
.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo
->Id
);
465 // Conflagrate - consumes Immolate or Shadowflame
466 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_CONFLAGRATE
)
468 Aura
const* aura
= NULL
; // found req. aura for damage calculation
470 Unit::AuraList
const &mPeriodic
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
471 for(Unit::AuraList::const_iterator i
= mPeriodic
.begin(); i
!= mPeriodic
.end(); ++i
)
473 // for caster applied auras only
474 if ((*i
)->GetSpellProto()->SpellFamilyName
!= SPELLFAMILY_WARLOCK
||
475 (*i
)->GetCasterGUID()!=m_caster
->GetGUID())
479 if ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000004))
481 aura
= *i
; // it selected always if exist
486 if ((*i
)->GetSpellProto()->SpellFamilyFlags2
& 0x00000002)
487 aura
= *i
; // remember but wait possible Immolate as primary priority
490 // found Immolate or Shadowflame
493 // DoT not have applied spell bonuses in m_amount
494 int32 damagetick
= m_caster
->SpellDamageBonus(unitTarget
, aura
->GetSpellProto(), aura
->GetModifier()->m_amount
, DOT
);
495 damage
+= damagetick
* 4;
497 // Glyph of Conflagrate
498 if (!m_caster
->HasAura(56235))
499 unitTarget
->RemoveAurasByCasterSpell(aura
->GetId(), m_caster
->GetGUID());
505 case SPELLFAMILY_PRIEST
:
507 // Shadow Word: Death - deals damage equal to damage done to caster
508 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000200000000))
509 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
510 // Improved Mind Blast (Mind Blast in shadow form bonus)
511 else if (m_caster
->m_form
== FORM_SHADOW
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00002000)))
513 Unit::AuraList
const& ImprMindBlast
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
514 for(Unit::AuraList::const_iterator i
= ImprMindBlast
.begin(); i
!= ImprMindBlast
.end(); ++i
)
516 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
517 ((*i
)->GetSpellProto()->SpellIconID
== 95))
519 int chance
= (*i
)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1
);
520 if (roll_chance_i(chance
))
522 m_caster
->CastSpell(unitTarget
, 48301, true);
529 case SPELLFAMILY_DRUID
:
532 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000800000)) && m_spellInfo
->SpellVisual
[0]==6587)
534 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
535 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
536 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
537 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
538 uint32 energy
= m_caster
->GetPower(POWER_ENERGY
);
539 uint32 used_energy
= energy
> 30 ? 30 : energy
;
540 damage
+= int32(used_energy
* multiple
);
541 m_caster
->SetPower(POWER_ENERGY
,energy
-used_energy
);
544 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000001000) && m_spellInfo
->Effect
[EFFECT_INDEX_2
] == SPELL_EFFECT_ADD_COMBO_POINTS
)
547 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
550 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
552 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
556 case SPELLFAMILY_ROGUE
:
559 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)))
561 // consume from stack dozes not more that have combo-points
562 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
565 // Lookup for Deadly poison (only attacker applied)
566 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
567 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
568 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
569 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x10000)) &&
570 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
575 // count consumed deadly poison doses at target
578 bool needConsume
= true;
579 uint32 spellId
= poison
->GetId();
580 uint32 doses
= poison
->GetStackAmount();
585 Unit::AuraList
const& auraList
= ((Player
*)m_caster
)->GetAurasByType(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL
);
586 for(Unit::AuraList::const_iterator iter
= auraList
.begin(); iter
!=auraList
.end(); ++iter
)
588 if ((*iter
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (*iter
)->GetSpellProto()->SpellIconID
== 1960)
590 if (int32 chance
= (*iter
)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2
))
591 if (roll_chance_i(chance
))
599 for (uint32 i
= 0; i
< doses
; ++i
)
600 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
603 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.09f
* doses
);
605 // Eviscerate and Envenom Bonus Damage (item set effect)
606 if(m_caster
->GetDummyAura(37169))
607 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
611 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00020000)) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
613 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
615 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
616 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
618 // Eviscerate and Envenom Bonus Damage (item set effect)
619 if(m_caster
->GetDummyAura(37169))
624 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000008))
626 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.21f
);
629 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
631 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
634 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000010000000))
636 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
640 case SPELLFAMILY_HUNTER
:
643 if (m_spellInfo
->SpellIconID
== 1578)
645 if (m_caster
->HasAura(57627)) // Charge 6 sec post-affect
649 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000000002)) && m_spellInfo
->SpellVisual
[0]==342)
651 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
654 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0008000000000000))
656 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
659 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000800)) && m_spellInfo
->maxLevel
> 0)
661 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
664 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
666 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
667 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
669 // Explosive Trap Effect
670 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000004))
672 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
676 case SPELLFAMILY_PALADIN
:
678 // Judgement of Righteousness - receive benefit from Spell Damage and Attack power
679 if (m_spellInfo
->Id
== 20187)
681 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
682 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
683 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
684 damage
+= int32(ap
* 0.2f
) + int32(holy
* 32 / 100);
686 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
687 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)) && m_spellInfo
->SpellIconID
==2292)
690 switch(m_spellInfo
->Id
)
692 case 53733: debuf_id
= 53742; break;// Judgement of Corruption -> Blood Corruption
693 case 31804: debuf_id
= 31803; break;// Judgement of Vengeance -> Holy Vengeance
697 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
698 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
699 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
700 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
701 // Get stack of Holy Vengeance on the target added by caster
703 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
704 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
706 if( ((*itr
)->GetId() == debuf_id
) && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
708 stacks
= (*itr
)->GetStackAmount();
712 // + 10% for each application of Holy Vengeance on the target
714 damage
+= damage
* stacks
* 10 /100;
716 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
717 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
719 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
720 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
721 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
722 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
724 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
725 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000008000000000))
727 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
728 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
729 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
730 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
732 // Hammer of the Righteous
733 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000))
735 // Add main hand dps * effect[2] amount
736 float average
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
737 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, EFFECT_INDEX_2
, m_spellInfo
->EffectBasePoints
[EFFECT_INDEX_2
], unitTarget
);
738 damage
+= count
* int32(average
* IN_MILLISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
740 // Shield of Righteousness
741 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
743 damage
+=int32(m_caster
->GetShieldBlockValue());
746 else if (m_spellInfo
->Id
== 54158)
748 // [1 + 0.25 * SPH + 0.16 * AP]
749 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.16f
);
760 void Spell::EffectDummy(SpellEffectIndex eff_idx
)
762 if (!unitTarget
&& !gameObjTarget
&& !itemTarget
)
765 // selection by spell family
766 switch(m_spellInfo
->SpellFamilyName
)
768 case SPELLFAMILY_GENERIC
:
770 switch(m_spellInfo
->Id
)
772 case 8063: // Deviate Fish
774 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
780 case 1: spell_id
= 8064; break; // Sleepy
781 case 2: spell_id
= 8065; break; // Invigorate
782 case 3: spell_id
= 8066; break; // Shrink
783 case 4: spell_id
= 8067; break; // Party Time!
784 case 5: spell_id
= 8068; break; // Healthy Spirit
786 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
789 case 8213: // Savory Deviate Delight
791 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
798 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
800 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
803 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
806 case 8593: // Symbol of life (restore creature to life)
807 case 31225: // Shimmering Vessel (restore creature to life)
809 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
812 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
815 case 13120: // net-o-matic
822 uint32 roll
= urand(0, 99);
824 if (roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
826 else if (roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
831 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
834 case 13567: // Dummy Trigger
836 // can be used for different aura triggering, so select by aura
837 if (!m_triggeredByAuraSpell
|| !unitTarget
)
840 switch(m_triggeredByAuraSpell
->Id
)
842 case 26467: // Persistent Shield
843 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
846 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
851 case 15998: // Capture Worg Pup
852 case 29435: // Capture Female Kaliri Hatchling
854 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
857 Creature
* creatureTarget
= (Creature
*)unitTarget
;
859 creatureTarget
->ForcedDespawn();
862 case 16589: // Noggenfogger Elixir
864 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
870 case 1: spell_id
= 16595; break;
871 case 2: spell_id
= 16593; break;
872 default:spell_id
= 16591; break;
875 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
878 case 17251: // Spirit Healer Res
883 Unit
* caster
= GetAffectiveCaster();
885 if (caster
&& caster
->GetTypeId() == TYPEID_PLAYER
)
887 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
888 data
<< uint64(unitTarget
->GetGUID());
889 ((Player
*)caster
)->GetSession()->SendPacket( &data
);
893 case 17271: // Test Fetid Skull
895 if (!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
898 uint32 spell_id
= roll_chance_i(50)
899 ? 17269 // Create Resonating Skull
900 : 17270; // Create Bone Dust
902 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
905 case 20577: // Cannibalize
908 m_caster
->CastSpell(m_caster
, 20578, false, NULL
);
912 case 23019: // Crystal Prison Dummy DND
914 if (!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
917 Creature
* creatureTarget
= (Creature
*)unitTarget
;
918 if (creatureTarget
->isPet())
921 GameObject
* pGameObj
= new GameObject
;
923 Map
*map
= creatureTarget
->GetMap();
925 // create before death for get proper coordinates
926 if (!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
927 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
928 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
) )
934 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
935 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
936 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
937 pGameObj
->SetSpellId(m_spellInfo
->Id
);
939 creatureTarget
->ForcedDespawn();
941 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
946 case 23074: // Arcanite Dragonling
951 m_caster
->CastSpell(m_caster
, 19804, true, m_CastItem
);
954 case 23075: // Mithril Mechanical Dragonling
959 m_caster
->CastSpell(m_caster
, 12749, true, m_CastItem
);
962 case 23076: // Mechanical Dragonling
967 m_caster
->CastSpell(m_caster
, 4073, true, m_CastItem
);
970 case 23133: // Gnomish Battle Chicken
975 m_caster
->CastSpell(m_caster
, 13166, true, m_CastItem
);
978 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
980 int32 r
= irand(0, 119);
981 if (r
< 20) // Transporter Malfunction - 1/6 polymorph
982 m_caster
->CastSpell(m_caster
, 23444, true);
983 else if (r
< 100) // Evil Twin - 4/6 evil twin
984 m_caster
->CastSpell(m_caster
, 23445, true);
985 else // Transporter Malfunction - 1/6 miss the target
986 m_caster
->CastSpell(m_caster
, 36902, true);
990 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
992 if (roll_chance_i(50)) // Gadgetzan Transporter - success
993 m_caster
->CastSpell(m_caster
, 23441, true);
994 else // Gadgetzan Transporter Failure - failure
995 m_caster
->CastSpell(m_caster
, 23446, true);
999 case 23645: // Hourglass Sand
1000 m_caster
->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
1002 case 23725: // Gift of Life (warrior bwl trinket)
1003 m_caster
->CastSpell(m_caster
, 23782, true);
1004 m_caster
->CastSpell(m_caster
, 23783, true);
1006 case 25860: // Reindeer Transformation
1008 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
1011 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
1012 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
1014 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
1016 //5 different spells used depending on mounted speed and if mount can fly or not
1017 if (flyspeed
>= 4.1f
)
1019 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
1020 else if (flyspeed
>= 3.8f
)
1022 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
1023 else if (flyspeed
>= 1.6f
)
1025 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
1026 else if (speed
>= 2.0f
)
1028 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
1031 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
1035 case 26074: // Holiday Cheer
1036 // implemented at client side
1038 case 28006: // Arcane Cloaking
1040 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1041 // Naxxramas Entry Flag Effect DND
1042 m_caster
->CastSpell(unitTarget
, 29294, true);
1046 case 29200: // Purify Helboar Meat
1048 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1051 uint32 spell_id
= roll_chance_i(50)
1052 ? 29277 // Summon Purified Helboar Meat
1053 : 29278; // Summon Toxic Helboar Meat
1055 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
1058 case 29858: // Soulshatter
1060 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
1061 m_caster
->CastSpell(unitTarget
,32835,true);
1065 case 30458: // Nigh Invulnerability
1070 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1071 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
1072 else // Complete Vulnerability - backfire in 14% casts
1073 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
1077 case 30507: // Poultryizer
1082 if (roll_chance_i(80)) // Poultryized! - success
1083 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
1084 else // Poultryized! - backfire 20%
1085 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
1089 case 33060: // Make a Wish
1091 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1094 uint32 spell_id
= 0;
1098 case 1: spell_id
= 33053; break; // Mr Pinchy's Blessing
1099 case 2: spell_id
= 33057; break; // Summon Mighty Mr. Pinchy
1100 case 3: spell_id
= 33059; break; // Summon Furious Mr. Pinchy
1101 case 4: spell_id
= 33062; break; // Tiny Magical Crawdad
1102 case 5: spell_id
= 33064; break; // Mr. Pinchy's Gift
1105 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
1108 case 35745: // Socrethar's Stone
1111 switch(m_caster
->GetAreaId())
1113 case 3900: spell_id
= 35743; break; // Socrethar Portal
1114 case 3742: spell_id
= 35744; break; // Socrethar Portal
1118 m_caster
->CastSpell(m_caster
, spell_id
, true);
1121 case 37674: // Chaos Blast
1126 int32 basepoints0
= 100;
1127 m_caster
->CastCustomSpell(unitTarget
, 37675, &basepoints0
, NULL
, NULL
, true);
1130 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1132 // selecting one from Bloodstained Fortune item
1134 switch(urand(1, 20))
1136 case 1: newitemid
= 32688; break;
1137 case 2: newitemid
= 32689; break;
1138 case 3: newitemid
= 32690; break;
1139 case 4: newitemid
= 32691; break;
1140 case 5: newitemid
= 32692; break;
1141 case 6: newitemid
= 32693; break;
1142 case 7: newitemid
= 32700; break;
1143 case 8: newitemid
= 32701; break;
1144 case 9: newitemid
= 32702; break;
1145 case 10: newitemid
= 32703; break;
1146 case 11: newitemid
= 32704; break;
1147 case 12: newitemid
= 32705; break;
1148 case 13: newitemid
= 32706; break;
1149 case 14: newitemid
= 32707; break;
1150 case 15: newitemid
= 32708; break;
1151 case 16: newitemid
= 32709; break;
1152 case 17: newitemid
= 32710; break;
1153 case 18: newitemid
= 32711; break;
1154 case 19: newitemid
= 32712; break;
1155 case 20: newitemid
= 32713; break;
1160 DoCreateItem(eff_idx
, newitemid
);
1163 case 42287: // Salvage Wreckage
1165 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1168 if (roll_chance_i(66))
1169 m_caster
->CastSpell(m_caster
, 42289, true, m_CastItem
);
1171 m_caster
->CastSpell(m_caster
, 42288, true);
1175 case 43036: // Dismembering Corpse
1177 if (!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1180 if (unitTarget
->HasAura(43059, EFFECT_INDEX_0
))
1183 unitTarget
->CastSpell(m_caster
, 43037, true);
1184 unitTarget
->CastSpell(unitTarget
, 43059, true);
1187 // Demon Broiled Surprise
1188 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1191 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1194 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1198 case 43882: // Scourging Crystal Controller Dummy
1200 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1203 // see spell dummy 50133
1204 unitTarget
->RemoveAurasDueToSpell(43874);
1207 case 44454: // Tasty Reef Fish
1209 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1212 m_caster
->CastSpell(unitTarget
, 44455, true, m_CastItem
);
1215 case 44875: // Complete Raptor Capture
1217 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1220 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1222 creatureTarget
->ForcedDespawn();
1224 //cast spell Raptor Capture Credit
1225 m_caster
->CastSpell(m_caster
, 42337, true, NULL
);
1228 case 44997: // Converting Sentry
1230 //Converted Sentry Credit
1231 m_caster
->CastSpell(m_caster
, 45009, true);
1234 case 45030: // Impale Emissary
1236 // Emissary of Hate Credit
1237 m_caster
->CastSpell(m_caster
, 45088, true);
1240 case 45980: // Re-Cursive Transmatter Injection
1242 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& unitTarget
)
1244 if (const SpellEntry
*pSpell
= sSpellStore
.LookupEntry(46022))
1246 m_caster
->CastSpell(unitTarget
, pSpell
, true);
1247 ((Player
*)m_caster
)->KilledMonsterCredit(pSpell
->EffectMiscValue
[EFFECT_INDEX_0
], 0);
1250 if (unitTarget
->GetTypeId() == TYPEID_UNIT
)
1251 ((Creature
*)unitTarget
)->ForcedDespawn();
1256 case 45685: // Magnataur On Death 2
1258 m_caster
->RemoveAurasDueToSpell(45673);
1259 m_caster
->RemoveAurasDueToSpell(45672);
1260 m_caster
->RemoveAurasDueToSpell(45677);
1261 m_caster
->RemoveAurasDueToSpell(45681);
1262 m_caster
->RemoveAurasDueToSpell(45683);
1265 case 45990: // Collect Oil
1267 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1270 if (const SpellEntry
*pSpell
= sSpellStore
.LookupEntry(45991))
1272 unitTarget
->CastSpell(unitTarget
, pSpell
, true);
1273 ((Creature
*)unitTarget
)->ForcedDespawn(GetSpellDuration(pSpell
) + 1);
1278 case 46167: // Planning for the Future: Create Snowfall Glade Pup Cover
1279 case 50926: // Gluttonous Lurkers: Create Zul'Drak Rat Cover
1280 case 51026: // Create Drakkari Medallion Cover
1281 case 51592: // Pickup Primordial Hatchling
1282 case 51961: // Captured Chicken Cover
1283 case 55364: // Create Ghoul Drool Cover
1285 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1290 switch(m_spellInfo
->Id
)
1292 case 46167: spellId
= 46773; break;
1293 case 50926: spellId
= 50927; break;
1294 case 51026: spellId
= 50737; break;
1295 case 51592: spellId
= 51593; break;
1296 case 51961: spellId
= 51037; break;
1297 case 55364: spellId
= 55363; break;
1300 if (const SpellEntry
*pSpell
= sSpellStore
.LookupEntry(spellId
))
1302 unitTarget
->CastSpell(m_caster
, spellId
, true);
1304 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1306 if (const SpellCastTimesEntry
*pCastTime
= sSpellCastTimesStore
.LookupEntry(pSpell
->CastingTimeIndex
))
1307 creatureTarget
->ForcedDespawn(pCastTime
->CastTime
+ 1);
1311 case 46485: // Greatmother's Soulcatcher
1313 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1316 if (const SpellEntry
*pSpell
= sSpellStore
.LookupEntry(46486))
1318 m_caster
->CastSpell(unitTarget
, pSpell
, true);
1320 if (const SpellEntry
*pSpellCredit
= sSpellStore
.LookupEntry(pSpell
->EffectMiscValue
[EFFECT_INDEX_0
]))
1321 ((Player
*)m_caster
)->KilledMonsterCredit(pSpellCredit
->EffectMiscValue
[EFFECT_INDEX_0
], 0);
1323 ((Creature
*)unitTarget
)->ForcedDespawn();
1328 case 46606: // Plague Canister Dummy
1330 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1333 unitTarget
->CastSpell(m_caster
, 43160, true);
1334 unitTarget
->setDeathState(JUST_DIED
);
1335 unitTarget
->SetHealth(0);
1338 case 46797: // Quest - Borean Tundra - Set Explosives Cart
1343 // Quest - Borean Tundra - Summon Explosives Cart
1344 unitTarget
->CastSpell(unitTarget
,46798,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1347 case 49357: // Brewfest Mount Transformation
1349 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1352 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
1355 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
1357 // Ram for Alliance, Kodo for Horde
1358 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1360 if (m_caster
->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1362 m_caster
->CastSpell(m_caster
, 43900, true);
1365 m_caster
->CastSpell(m_caster
, 43899, true);
1369 if (((Player
*)m_caster
)->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1371 m_caster
->CastSpell(m_caster
, 49379, true);
1374 m_caster
->CastSpell(m_caster
, 49378, true);
1378 case 50133: // Scourging Crystal Controller
1380 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1383 if (unitTarget
->HasAura(43874))
1385 // someone else is already channeling target
1386 if (unitTarget
->HasAura(43878))
1389 m_caster
->CastSpell(unitTarget
, 43878, true, m_CastItem
);
1394 case 50243: // Teach Language
1396 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1399 // spell has a 1/3 chance to trigger one of the below
1400 if (roll_chance_i(66))
1403 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1405 // 1000001 - gnomish binary
1406 m_caster
->CastSpell(m_caster
, 50242, true);
1410 // 01001000 - goblin binary
1411 m_caster
->CastSpell(m_caster
, 50246, true);
1416 case 51276: // Incinerate Corpse
1418 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1421 unitTarget
->CastSpell(unitTarget
, 51278, true);
1422 unitTarget
->CastSpell(m_caster
, 51279, true);
1424 unitTarget
->setDeathState(JUST_DIED
);
1427 case 51330: // Shoot RJR
1433 if (roll_chance_i(75))
1434 m_caster
->CastSpell(unitTarget
, roll_chance_i(50) ? 51332 : 51366, true, m_CastItem
);
1436 m_caster
->CastSpell(unitTarget
, 51331, true, m_CastItem
);
1440 case 51333: // Dig For Treasure
1445 if (roll_chance_i(75))
1446 m_caster
->CastSpell(unitTarget
, 51370, true, m_CastItem
);
1448 m_caster
->CastSpell(m_caster
, 51345, true);
1452 case 51582: // Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1454 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1457 if (BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1458 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1460 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1463 case 52308: // Take Sputum Sample
1467 case EFFECT_INDEX_0
:
1469 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(EFFECT_INDEX_0
);
1470 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(EFFECT_INDEX_1
);
1472 if (m_caster
->HasAura(reqAuraID
, EFFECT_INDEX_0
))
1473 m_caster
->CastSpell(m_caster
, spellID
, true, NULL
);
1476 case EFFECT_INDEX_1
:
1477 return; // additional data for dummy[0]
1481 case 52759: // Ancestral Awakening
1486 m_caster
->CastCustomSpell(unitTarget
, 52752, &damage
, NULL
, NULL
, true);
1489 case 52845: // Brewfest Mount Transformation (Faction Swap)
1491 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1494 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
1497 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
1499 // Ram for Horde, Kodo for Alliance
1500 if (((Player
*)m_caster
)->GetTeam() == HORDE
)
1502 if (m_caster
->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1503 // Swift Brewfest Ram, 100% Ram
1504 m_caster
->CastSpell(m_caster
, 43900, true);
1506 // Brewfest Ram, 60% Ram
1507 m_caster
->CastSpell(m_caster
, 43899, true);
1511 if (((Player
*)m_caster
)->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1512 // Great Brewfest Kodo, 100% Kodo
1513 m_caster
->CastSpell(m_caster
, 49379, true);
1515 // Brewfest Riding Kodo, 60% Kodo
1516 m_caster
->CastSpell(m_caster
, 49378, true);
1520 case 53341: // Rune of Cinderglacier
1521 case 53343: // Rune of Razorice
1523 // Runeforging Credit
1524 m_caster
->CastSpell(m_caster
, 54586, true);
1527 case 55004: // Nitro Boosts
1532 if (roll_chance_i(95)) // Nitro Boosts - success
1533 m_caster
->CastSpell(m_caster
, 54861, true, m_CastItem
);
1534 else // Knocked Up - backfire 5%
1535 m_caster
->CastSpell(m_caster
, 46014, true, m_CastItem
);
1539 case 55818: // Hurl Boulder
1541 // unclear how many summon min/max random, best guess below
1542 uint32 random
= urand(3,5);
1544 for(uint32 i
= 0; i
< random
; ++i
)
1545 m_caster
->CastSpell(m_caster
, 55528, true);
1549 case 58418: // Portal to Orgrimmar
1550 case 58420: // Portal to Stormwind
1551 return; // implemented in EffectScript[0]
1552 case 58601: // Remove Flight Auras
1554 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_FLY
);
1555 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
);
1558 case 59640: // Underbelly Elixir
1560 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1563 uint32 spell_id
= 0;
1566 case 1: spell_id
= 59645; break;
1567 case 2: spell_id
= 59831; break;
1568 case 3: spell_id
= 59843; break;
1571 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
1574 case 60932: // Disengage (one from creature versions)
1579 m_caster
->CastSpell(unitTarget
,60934,true,NULL
);
1582 case 67019: // Flask of the North
1584 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1587 uint32 spell_id
= 0;
1588 switch(m_caster
->getClass())
1591 case CLASS_DEATH_KNIGHT
:
1592 spell_id
= 67018; // STR for Warriors, Death Knights
1596 spell_id
= 67017; // AP for Rogues, Hunters
1601 spell_id
= 67016; // SPD for Priests, Mages, Warlocks
1605 spell_id
= roll_chance_i(50) ? 67016 : 67017;
1610 // random (SPD, STR)
1611 spell_id
= roll_chance_i(50) ? 67016 : 67018;
1614 m_caster
->CastSpell(m_caster
, spell_id
, true);
1620 case SPELLFAMILY_MAGE
:
1622 switch(m_spellInfo
->Id
)
1624 case 11958: // Cold Snap
1626 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1629 // immediately finishes the cooldown on Frost spells
1630 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1631 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1633 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1635 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1636 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1637 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0)
1639 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
, true);
1646 case 31687: // Summon Water Elemental
1648 if (m_caster
->HasAura(70937)) // Glyph of Eternal Water (permanent limited by known spells version)
1649 m_caster
->CastSpell(m_caster
, 70908, true);
1650 else // temporary version
1651 m_caster
->CastSpell(m_caster
, 70907, true);
1655 case 32826: // Polymorph Cast Visual
1657 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1659 //Polymorph Cast Visual Rank 1
1660 const uint32 spell_list
[6] =
1662 32813, // Squirrel Form
1663 32816, // Giraffe Form
1664 32817, // Serpent Form
1665 32818, // Dragonhawk Form
1666 32819, // Worgen Form
1669 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1676 if (eff_idx
== EFFECT_INDEX_1
&& m_spellInfo
->Effect
[EFFECT_INDEX_0
] == SPELL_EFFECT_CREATE_ITEM
)
1678 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1681 // checked in create item check, avoid unexpected
1682 if (Item
* item
= ((Player
*)m_caster
)->GetItemByLimitedCategory(ITEM_LIMIT_CATEGORY_MANA_GEM
))
1683 if (item
->HasMaxCharges())
1686 unitTarget
->CastSpell( unitTarget
, m_spellInfo
->CalculateSimpleValue(eff_idx
), true, m_CastItem
);
1691 case SPELLFAMILY_WARRIOR
:
1694 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x1)) && m_spellInfo
->SpellVisual
[0] == 867)
1696 int32 chargeBasePoints0
= damage
;
1697 m_caster
->CastCustomSpell(m_caster
, 34846, &chargeBasePoints0
, NULL
, NULL
, true);
1701 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000))
1706 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1708 // up to max 30 rage cost
1712 // Glyph of Execution bonus
1713 uint32 rage_modified
= rage
;
1715 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1716 rage_modified
+= aura
->GetModifier()->m_amount
*10;
1718 int32 basePoints0
= damage
+int32(rage_modified
* m_spellInfo
->DmgMultiplier
[eff_idx
] +
1719 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1721 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1724 if (m_caster
->HasAura(52437))
1726 Unit::AuraList
const& auras
= m_caster
->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL
);
1727 for (Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
1729 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1730 if ((*itr
)->GetSpellProto()->SpellIconID
== 1989)
1732 // saved rage top stored in next affect
1733 uint32 lastrage
= (*itr
)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1
)*10;
1741 m_caster
->SetPower(POWER_RAGE
,m_caster
->GetPower(POWER_RAGE
)-rage
);
1745 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000200000))
1750 // dummy cast itself ignored by client in logs
1751 m_caster
->CastCustomSpell(unitTarget
,50782,&damage
,NULL
,NULL
,true);
1755 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000))
1757 m_damage
+= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
1761 switch(m_spellInfo
->Id
)
1768 m_caster
->CastSpell(unitTarget
, 21887, true);// spell mod
1774 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1775 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1781 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1787 case SPELLFAMILY_WARLOCK
:
1790 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000040000))
1792 // In 303 exist spirit depend
1793 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1794 switch (m_spellInfo
->Id
)
1796 case 1454: damage
+=spirit
; break;
1797 case 1455: damage
+=spirit
*15/10; break;
1798 case 1456: damage
+=spirit
*2; break;
1799 case 11687: damage
+=spirit
*25/10; break;
1803 case 57946: damage
+=spirit
*3; break;
1805 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1808 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1809 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1810 if (unitTarget
&& (int32(unitTarget
->GetHealth()) > damage
))
1812 // Shouldn't Appear in Combat Log
1813 unitTarget
->ModifyHealth(-damage
);
1815 int32 mana
= damage
;
1816 // Improved Life Tap mod
1817 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1818 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1820 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1821 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1823 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1826 int32 manaFeedVal
= 0;
1827 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1828 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1830 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1831 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1833 if (manaFeedVal
> 0)
1835 manaFeedVal
= manaFeedVal
* mana
/ 100;
1836 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1840 SendCastResult(SPELL_FAILED_FIZZLE
);
1846 case SPELLFAMILY_PRIEST
:
1849 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0080000000000000))
1856 switch(m_spellInfo
->Id
)
1858 case 47540: hurt
= 47758; heal
= 47757; break;
1859 case 53005: hurt
= 53001; heal
= 52986; break;
1860 case 53006: hurt
= 53002; heal
= 52987; break;
1861 case 53007: hurt
= 53003; heal
= 52988; break;
1863 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1867 // prevent interrupted message for main spell
1870 // replace cast by selected spell, this also make it interruptible including target death case
1871 if (m_caster
->IsFriendlyTo(unitTarget
))
1872 m_caster
->CastSpell(unitTarget
, heal
, false);
1874 m_caster
->CastSpell(unitTarget
, hurt
, false);
1880 case SPELLFAMILY_DRUID
:
1883 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000100)
1885 //Shapeshifting into an animal form or mounting cancels the effect.
1886 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1888 if(m_triggeredByAuraSpell
)
1889 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1893 //Any effect which causes you to lose control of your character will supress the starfall effect.
1894 if (m_caster
->hasUnitState(UNIT_STAT_NO_FREE_MOVE
))
1897 switch(m_spellInfo
->Id
)
1899 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1900 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1901 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1902 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1904 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1910 case SPELLFAMILY_ROGUE
:
1912 switch(m_spellInfo
->Id
)
1916 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1919 Player
*pCaster
= ((Player
*)m_caster
);
1921 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1925 // all poison enchantments is temporary
1926 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1930 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1934 for (int s
= 0; s
< 3; ++s
)
1936 if (pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1939 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1940 if (!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1943 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1946 m_caster
->CastSpell(unitTarget
, 5940, true);
1949 case 14185: // Preparation
1951 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1954 //immediately finishes the cooldown on certain Rogue abilities
1955 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1956 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1958 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1960 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000024000000860)))
1961 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
1967 case 31231: // Cheat Death
1969 m_caster
->CastSpell(m_caster
, 45182, true);
1975 case SPELLFAMILY_HUNTER
:
1978 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
1980 if (!unitTarget
|| !unitTarget
->isAlive())
1985 // check dazed affect
1986 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1987 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1989 if ((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
2002 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000400000000000))
2004 Unit
* target
= unitTarget
;
2006 switch(m_spellInfo
->Id
)
2008 case 57635: spellid
= 57636; break; // one from creature cases
2009 case 61507: spellid
= 61508; break; // one from creature cases
2011 sLog
.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo
->Id
);
2014 if (!target
|| !target
->isAlive())
2016 m_caster
->CastSpell(target
,spellid
,true,NULL
);
2019 switch(m_spellInfo
->Id
)
2021 case 23989: // Readiness talent
2023 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2026 //immediately finishes the cooldown for hunter abilities
2027 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
2028 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
2030 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2032 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
2033 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
2039 case 37506: // Scatter Shot
2041 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2044 // break Auto Shot and autohit
2045 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
2046 m_caster
->AttackStop();
2047 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
2055 int32 healthModSpellBasePoints0
= int32(unitTarget
->GetMaxHealth() * 0.3);
2056 unitTarget
->CastCustomSpell(unitTarget
, 53479, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
2062 Pet
* pet
= m_caster
->GetPet();
2063 if (!pet
|| !unitTarget
)
2066 pet
->CastSpell(unitTarget
, m_spellInfo
->CalculateSimpleValue(eff_idx
), true);
2072 case SPELLFAMILY_PALADIN
:
2074 switch(m_spellInfo
->SpellIconID
)
2076 case 156: // Holy Shock
2084 switch(m_spellInfo
->Id
)
2086 case 20473: hurt
= 25912; heal
= 25914; break;
2087 case 20929: hurt
= 25911; heal
= 25913; break;
2088 case 20930: hurt
= 25902; heal
= 25903; break;
2089 case 27174: hurt
= 27176; heal
= 27175; break;
2090 case 33072: hurt
= 33073; heal
= 33074; break;
2091 case 48824: hurt
= 48822; heal
= 48820; break;
2092 case 48825: hurt
= 48823; heal
= 48821; break;
2094 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
2098 if (m_caster
->IsFriendlyTo(unitTarget
))
2099 m_caster
->CastSpell(unitTarget
, heal
, true);
2101 m_caster
->CastSpell(unitTarget
, hurt
, true);
2105 case 561: // Judgement of command
2110 uint32 spell_id
= m_currentBasePoints
[eff_idx
]+1;
2111 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
2115 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
2120 switch(m_spellInfo
->Id
)
2122 case 31789: // Righteous Defense (step 1)
2124 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
2126 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
2130 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
2131 Unit
* friendTarget
= !unitTarget
|| unitTarget
->IsFriendlyTo(m_caster
) ? unitTarget
: unitTarget
->getVictim();
2134 Player
* player
= friendTarget
->GetCharmerOrOwnerPlayerOrPlayerItself();
2135 if (!player
|| !player
->IsInSameRaidWith((Player
*)m_caster
))
2136 friendTarget
= NULL
;
2139 // non-standard cast requirement check
2140 if (!friendTarget
|| friendTarget
->getAttackers().empty())
2142 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
,true);
2143 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
2147 // Righteous Defense (step 2) (in old version 31980 dummy effect)
2148 // Clear targets for eff 1
2149 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
2150 ihit
->effectMask
&= ~(1<<1);
2152 // not empty (checked), copy
2153 Unit::AttackerSet attackers
= friendTarget
->getAttackers();
2155 // selected from list 3
2156 for(uint32 i
= 0; i
< std::min(size_t(3),attackers
.size()); ++i
)
2158 Unit::AttackerSet::iterator aItr
= attackers
.begin();
2159 std::advance(aItr
, rand() % attackers
.size());
2160 AddUnitTarget((*aItr
), EFFECT_INDEX_1
);
2161 attackers
.erase(aItr
);
2164 // now let next effect cast spell at each target.
2167 case 37877: // Blessing of Faith
2172 uint32 spell_id
= 0;
2173 switch(unitTarget
->getClass())
2175 case CLASS_DRUID
: spell_id
= 37878; break;
2176 case CLASS_PALADIN
: spell_id
= 37879; break;
2177 case CLASS_PRIEST
: spell_id
= 37880; break;
2178 case CLASS_SHAMAN
: spell_id
= 37881; break;
2179 default: return; // ignore for not healing classes
2182 m_caster
->CastSpell(m_caster
, spell_id
, true);
2188 case SPELLFAMILY_SHAMAN
:
2191 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000)) && m_spellInfo
->SpellIconID
==1673)
2194 m_caster
->CastSpell(unitTarget
, 52025, true);
2197 // Healing Stream Totem
2198 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
2202 if (Unit
*owner
= m_caster
->GetOwner())
2204 // Restorative Totems
2205 Unit::AuraList
const& mDummyAuras
= owner
->GetAurasByType(SPELL_AURA_DUMMY
);
2206 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
2207 // only its have dummy with specific icon
2208 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_SHAMAN
&& (*i
)->GetSpellProto()->SpellIconID
== 338)
2209 damage
+= (*i
)->GetModifier()->m_amount
* damage
/ 100;
2211 // Glyph of Healing Stream Totem
2212 if (Aura
*dummy
= owner
->GetDummyAura(55456))
2213 damage
+= dummy
->GetModifier()->m_amount
* damage
/ 100;
2215 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, NULL
, NULL
, true, 0, 0, m_originalCasterGUID
);
2219 // Mana Spring Totem
2220 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
2222 if (!unitTarget
|| unitTarget
->getPowerType()!=POWER_MANA
)
2224 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
2227 if (m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
2229 if (!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
2231 // Glyph of Mana Tide
2232 if (Unit
*owner
= m_caster
->GetOwner())
2233 if (Aura
*dummy
= owner
->GetDummyAura(55441))
2234 damage
+=dummy
->GetModifier()->m_amount
;
2235 // Regenerate 6% of Total Mana Every 3 secs
2236 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
2237 m_caster
->CastCustomSpell(unitTarget
, 39609, &EffectBasePoints0
, NULL
, NULL
, true, NULL
, NULL
, m_originalCasterGUID
);
2241 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
2243 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2245 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
2248 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
2249 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2250 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
2252 if ((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
2253 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000200000)) &&
2254 (*itr
)->GetCastItemGUID() == item
->GetGUID())
2256 m_damage
+= m_damage
* damage
/ 100;
2264 if (m_spellInfo
->SpellIconID
== 33)
2267 Totem
* totem
= m_caster
->GetTotem(TOTEM_SLOT_FIRE
);
2271 uint32 triggered_spell_id
;
2272 switch(m_spellInfo
->Id
)
2274 case 1535: triggered_spell_id
= 8349; break;
2275 case 8498: triggered_spell_id
= 8502; break;
2276 case 8499: triggered_spell_id
= 8503; break;
2277 case 11314: triggered_spell_id
= 11306; break;
2278 case 11315: triggered_spell_id
= 11307; break;
2279 case 25546: triggered_spell_id
= 25535; break;
2280 case 25547: triggered_spell_id
= 25537; break;
2281 case 61649: triggered_spell_id
= 61650; break;
2282 case 61657: triggered_spell_id
= 61654; break;
2286 totem
->CastSpell(totem
, triggered_spell_id
, true, NULL
, NULL
, m_caster
->GetGUID());
2289 totem
->CastSpell(totem
, 19823, true, NULL
, NULL
, m_caster
->GetGUID());
2294 case SPELLFAMILY_DEATHKNIGHT
:
2297 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x002000))
2299 if (m_caster
->IsFriendlyTo(unitTarget
))
2301 if (unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
2304 int32 bp
= int32(damage
* 1.5f
);
2305 m_caster
->CastCustomSpell(unitTarget
, 47633, &bp
, NULL
, NULL
, true);
2310 m_caster
->CastCustomSpell(unitTarget
, 47632, &bp
, NULL
, NULL
, true);
2315 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000100000000000))
2317 m_caster
->CastSpell(m_caster
, 51209, true);
2321 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000010))
2324 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
2325 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
2327 if (itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
2328 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
2329 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
2338 int32 bp
= int32(count
* m_caster
->GetMaxHealth() * m_spellInfo
->DmgMultiplier
[EFFECT_INDEX_0
] / 100);
2340 // Improved Death Strike (percent stored in not existed EFFECT_INDEX_2 effect base points)
2341 Unit::AuraList
const& auraMod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
2342 for(Unit::AuraList::const_iterator iter
= auraMod
.begin(); iter
!= auraMod
.end(); ++iter
)
2344 // only required spell have spellicon for SPELL_AURA_ADD_FLAT_MODIFIER
2345 if ((*iter
)->GetSpellProto()->SpellIconID
== 2751 && (*iter
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DEATHKNIGHT
)
2347 bp
+= (*iter
)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2
) * bp
/ 100;
2352 m_caster
->CastCustomSpell(m_caster
, 45470, &bp
, NULL
, NULL
, true);
2360 if (PetAura
const* petSpell
= sSpellMgr
.GetPetAura(m_spellInfo
->Id
, eff_idx
))
2362 m_caster
->AddPetAura(petSpell
);
2366 // Script based implementation. Must be used only for not good for implementation in core spell effects
2367 // So called only for not processed cases
2369 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, eff_idx
, gameObjTarget
);
2370 else if (unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
2371 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, eff_idx
, (Creature
*)unitTarget
);
2372 else if (itemTarget
)
2373 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, eff_idx
, itemTarget
);
2376 void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx
)
2378 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[eff_idx
];
2381 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2385 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2390 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
2393 void Spell::EffectTriggerRitualOfSummoning(SpellEffectIndex eff_idx
)
2395 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[eff_idx
];
2396 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2400 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2406 m_caster
->CastSpell(unitTarget
,spellInfo
,false);
2409 void Spell::EffectForceCast(SpellEffectIndex eff_idx
)
2414 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[eff_idx
];
2417 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2421 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2425 unitTarget
->CastSpell(unitTarget
, spellInfo
, true, NULL
, NULL
, m_originalCasterGUID
);
2428 void Spell::EffectTriggerSpell(SpellEffectIndex effIndex
)
2430 // only unit case known
2433 if(gameObjTarget
|| itemTarget
)
2434 sLog
.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo
->Id
);
2438 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effIndex
];
2441 switch(triggered_spell_id
)
2443 // Vanish (not exist)
2446 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
2447 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
2448 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
2450 // if this spell is given to NPC it must handle rest by it's own AI
2451 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2454 // get highest rank of the Stealth spell
2456 const PlayerSpellMap
& sp_list
= ((Player
*)unitTarget
)->GetSpellMap();
2457 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
2459 // only highest rank is shown in spell book, so simply check if shown in spell book
2460 if (!itr
->second
.active
|| itr
->second
.disabled
|| itr
->second
.state
== PLAYERSPELL_REMOVED
)
2463 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2467 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
2469 spellId
= spellInfo
->Id
;
2474 // no Stealth spell found
2478 // reset cooldown on it if needed
2479 if (((Player
*)unitTarget
)->HasSpellCooldown(spellId
))
2480 ((Player
*)unitTarget
)->RemoveSpellCooldown(spellId
);
2482 m_caster
->CastSpell(unitTarget
, spellId
, true);
2486 case 23770: // Sayge's Dark Fortune of *
2487 // not exist, common cooldown can be implemented in scripts if need.
2489 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2493 SpellEntry
const* spell
= sSpellStore
.LookupEntry(24575);
2497 for (uint32 j
=0; j
< spell
->StackAmount
; ++j
)
2498 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2501 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2505 SpellEntry
const* spell
= sSpellStore
.LookupEntry(26464);
2509 for (uint32 j
=0; j
< spell
->StackAmount
; ++j
)
2510 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2513 // Righteous Defense
2516 m_caster
->CastSpell(unitTarget
, 31790, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2522 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2523 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
2525 // remove all harmful spells on you...
2526 if( // ignore positive and passive auras
2527 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
2528 // ignore physical auras
2529 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
2531 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
2532 iter
= Auras
.begin();
2537 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2540 if (Unit
*pet
= unitTarget
->GetPet())
2541 pet
->CastSpell(pet
, 28305, true);
2547 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2550 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2554 // select formal caster for triggered spell
2555 Unit
* caster
= m_caster
;
2557 // some triggered spells require specific equipment
2558 if (spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
2560 // main hand weapon required
2561 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
2563 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
, true, false);
2565 // skip spell if no weapon in slot or broken
2569 // skip spell if weapon not fit to triggered spell
2570 if (!item
->IsFitToSpellRequirements(spellInfo
))
2574 // offhand hand weapon required
2575 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
2577 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
, true, false);
2579 // skip spell if no weapon in slot or broken
2583 // skip spell if weapon not fit to triggered spell
2584 if (!item
->IsFitToSpellRequirements(spellInfo
))
2590 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2591 // so this just for speedup places in else
2592 caster
= IsSpellWithCasterSourceTargetsOnly(spellInfo
) ? unitTarget
: m_caster
;
2595 caster
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
2598 void Spell::EffectTriggerMissileSpell(SpellEffectIndex effect_idx
)
2600 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2603 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2607 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2608 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2613 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2615 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2618 void Spell::EffectJump(SpellEffectIndex eff_idx
)
2620 if(m_caster
->isInFlight())
2623 // Init dest coordinates
2625 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2627 x
= m_targets
.m_destX
;
2628 y
= m_targets
.m_destY
;
2629 z
= m_targets
.m_destZ
;
2631 if(m_spellInfo
->EffectImplicitTargetA
[eff_idx
] == TARGET_BEHIND_VICTIM
)
2633 // explicit cast data from client or server-side cast
2634 // some spell at client send caster
2635 Unit
* pTarget
= NULL
;
2636 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2637 pTarget
= m_targets
.getUnitTarget();
2638 else if(unitTarget
->getVictim())
2639 pTarget
= m_caster
->getVictim();
2640 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2641 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2643 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2646 o
= m_caster
->GetOrientation();
2650 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2651 o
= m_caster
->GetOrientation();
2653 else if(gameObjTarget
)
2655 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2656 o
= m_caster
->GetOrientation();
2660 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2664 m_caster
->NearTeleportTo(x
, y
, z
, o
, true);
2667 void Spell::EffectTeleportUnits(SpellEffectIndex eff_idx
)
2669 if(!unitTarget
|| unitTarget
->isInFlight())
2672 switch (m_spellInfo
->EffectImplicitTargetB
[eff_idx
])
2674 case TARGET_INNKEEPER_COORDINATES
:
2676 // Only players can teleport to innkeeper
2677 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2680 ((Player
*)unitTarget
)->TeleportToHomebind(unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2683 case TARGET_AREAEFFECT_INSTANT
: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2684 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2686 SpellTargetPosition
const* st
= sSpellMgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2689 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2693 if(st
->target_mapId
==unitTarget
->GetMapId())
2694 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2695 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2696 ((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);
2699 case TARGET_BEHIND_VICTIM
:
2701 Unit
*pTarget
= NULL
;
2703 // explicit cast data from client or server-side cast
2704 // some spell at client send caster
2705 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2706 pTarget
= m_targets
.getUnitTarget();
2707 else if(unitTarget
->getVictim())
2708 pTarget
= unitTarget
->getVictim();
2709 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2710 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2712 // Init dest coordinates
2713 float x
= m_targets
.m_destX
;
2714 float y
= m_targets
.m_destY
;
2715 float z
= m_targets
.m_destZ
;
2716 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2717 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2722 // If not exist data for dest location - return
2723 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2725 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", eff_idx
, m_spellInfo
->EffectImplicitTargetB
[eff_idx
], m_spellInfo
->Id
);
2728 // Init dest coordinates
2729 float x
= m_targets
.m_destX
;
2730 float y
= m_targets
.m_destY
;
2731 float z
= m_targets
.m_destZ
;
2732 float orientation
= unitTarget
->GetOrientation();
2734 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2739 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2740 switch ( m_spellInfo
->Id
)
2742 // Dimensional Ripper - Everlook
2745 int32 r
= irand(0, 119);
2746 if ( r
>= 70 ) // 7/12 success
2748 if ( r
< 100 ) // 4/12 evil twin
2749 m_caster
->CastSpell(m_caster
, 23445, true);
2751 m_caster
->CastSpell(m_caster
, 23449, true);
2755 // Ultrasafe Transporter: Toshley's Station
2758 if ( roll_chance_i(50) ) // 50% success
2760 int32 rand_eff
= urand(1, 7);
2764 // soul split - evil
2765 m_caster
->CastSpell(m_caster
, 36900, true);
2768 // soul split - good
2769 m_caster
->CastSpell(m_caster
, 36901, true);
2772 // Increase the size
2773 m_caster
->CastSpell(m_caster
, 36895, true);
2776 // Decrease the size
2777 m_caster
->CastSpell(m_caster
, 36893, true);
2782 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2783 m_caster
->CastSpell(m_caster
, 36897, true);
2785 m_caster
->CastSpell(m_caster
, 36899, true);
2790 m_caster
->CastSpell(m_caster
, 36940, true);
2794 m_caster
->CastSpell(m_caster
, 23445, true);
2800 // Dimensional Ripper - Area 52
2803 if ( roll_chance_i(50) ) // 50% success
2805 int32 rand_eff
= urand(1, 4);
2809 // soul split - evil
2810 m_caster
->CastSpell(m_caster
, 36900, true);
2813 // soul split - good
2814 m_caster
->CastSpell(m_caster
, 36901, true);
2817 // Increase the size
2818 m_caster
->CastSpell(m_caster
, 36895, true);
2823 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2824 m_caster
->CastSpell(m_caster
, 36897, true);
2826 m_caster
->CastSpell(m_caster
, 36899, true);
2836 void Spell::EffectApplyAura(SpellEffectIndex eff_idx
)
2841 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2842 if ( (!unitTarget
->isAlive() && !(IsDeathOnlySpell(m_spellInfo
) || IsDeathPersistentSpell(m_spellInfo
))) &&
2843 (unitTarget
->GetTypeId() != TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2846 Unit
* caster
= GetAffectiveCaster();
2849 // FIXME: currently we can't have auras applied explIcitly by gameobjects
2850 // so for auras from wild gameobjects (no owner) target used
2851 if (m_originalCasterGUID
.IsGameobject())
2852 caster
= unitTarget
;
2857 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[eff_idx
]);
2859 Aura
* Aur
= CreateAura(m_spellInfo
, eff_idx
, &m_currentBasePoints
[eff_idx
], unitTarget
, caster
, m_CastItem
);
2861 // Now Reduce spell duration using data received at spell hit
2862 int32 duration
= Aur
->GetAuraMaxDuration();
2863 int32 limitduration
= GetDiminishingReturnsLimitDuration(m_diminishGroup
,m_spellInfo
);
2864 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
, duration
, m_caster
, m_diminishLevel
,limitduration
);
2865 Aur
->setDiminishGroup(m_diminishGroup
);
2867 // if Aura removed and deleted, do not continue.
2868 if(duration
== 0 && !(Aur
->IsPermanent()))
2874 if(duration
!= Aur
->GetAuraMaxDuration())
2876 Aur
->SetAuraMaxDuration(duration
);
2877 Aur
->SetAuraDuration(duration
);
2880 unitTarget
->AddAura(Aur
);
2883 void Spell::EffectUnlearnSpecialization(SpellEffectIndex eff_idx
)
2885 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2888 Player
*_player
= (Player
*)unitTarget
;
2889 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[eff_idx
];
2891 _player
->removeSpell(spellToUnlearn
);
2893 sLog
.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2896 void Spell::EffectPowerDrain(SpellEffectIndex eff_idx
)
2898 if(m_spellInfo
->EffectMiscValue
[eff_idx
] < 0 || m_spellInfo
->EffectMiscValue
[eff_idx
] >= MAX_POWERS
)
2901 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[eff_idx
]);
2905 if(!unitTarget
->isAlive())
2907 if(unitTarget
->getPowerType() != drain_power
)
2912 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2914 //add spell damage bonus
2915 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2917 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2918 uint32 power
= damage
;
2919 if (drain_power
== POWER_MANA
)
2920 power
-= unitTarget
->GetSpellCritDamageReduction(power
);
2923 if(curPower
< power
)
2924 new_damage
= curPower
;
2928 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2930 // Don`t restore from self drain
2931 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2933 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[eff_idx
];
2934 if(manaMultiplier
==0)
2937 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2938 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2940 int32 gain
= int32(new_damage
* manaMultiplier
);
2942 m_caster
->EnergizeBySpell(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
2946 void Spell::EffectSendEvent(SpellEffectIndex effectIndex
)
2949 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2951 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[effectIndex
], m_spellInfo
->Id
);
2952 m_caster
->GetMap()->ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[effectIndex
], m_caster
, focusObject
);
2955 void Spell::EffectPowerBurn(SpellEffectIndex eff_idx
)
2957 if (m_spellInfo
->EffectMiscValue
[eff_idx
] < 0 || m_spellInfo
->EffectMiscValue
[eff_idx
] >= MAX_POWERS
)
2960 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[eff_idx
]);
2964 if (!unitTarget
->isAlive())
2966 if (unitTarget
->getPowerType()!=powertype
)
2971 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2972 if (m_spellInfo
->ManaCostPercentage
)
2974 int32 maxdamage
= m_caster
->GetMaxPower(powertype
) * damage
* 2 / 100;
2975 damage
= unitTarget
->GetMaxPower(powertype
) * damage
/ 100;
2976 if(damage
> maxdamage
)
2980 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2982 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2983 int32 power
= damage
;
2984 if (powertype
== POWER_MANA
)
2985 power
-= unitTarget
->GetSpellCritDamageReduction(power
);
2987 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2989 unitTarget
->ModifyPower(powertype
, -new_damage
);
2990 float multiplier
= m_spellInfo
->EffectMultipleValue
[eff_idx
];
2992 if (Player
*modOwner
= m_caster
->GetSpellModOwner())
2993 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2995 new_damage
= int32(new_damage
* multiplier
);
2996 m_damage
+= new_damage
;
2999 void Spell::EffectHeal(SpellEffectIndex
/*eff_idx*/)
3001 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
3003 // Try to get original caster
3004 Unit
*caster
= GetAffectiveCaster();
3008 int32 addhealth
= damage
;
3010 // Seal of Light proc
3011 if (m_spellInfo
->Id
== 20167)
3013 float ap
= caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
3014 int32 holy
= caster
->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellInfo
)) +
3015 caster
->SpellBaseHealingBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
3016 addhealth
+= int32(ap
* 0.15) + int32(holy
* 15 / 100);
3018 // Vessel of the Naaru (Vial of the Sunwell trinket)
3019 else if (m_spellInfo
->Id
== 45064)
3021 // Amount of heal - depends from stacked Holy Energy
3022 int damageAmount
= 0;
3023 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
3024 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
3025 if ((*i
)->GetId() == 45062)
3026 damageAmount
+=(*i
)->GetModifier()->m_amount
;
3028 m_caster
->RemoveAurasDueToSpell(45062);
3030 addhealth
+= damageAmount
;
3032 // Death Pact (percent heal)
3033 else if (m_spellInfo
->Id
==48743)
3034 addhealth
= addhealth
* unitTarget
->GetMaxHealth() / 100;
3035 // Swiftmend - consumes Regrowth or Rejuvenation
3036 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
3038 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
3039 // find most short by duration
3040 Aura
*targetAura
= NULL
;
3041 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
3043 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
&&
3044 // Regrowth or Rejuvenation 0x40 | 0x10
3045 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000050)))
3047 if (!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
3054 sLog
.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUIDLow(), unitTarget
->GetTypeId());
3060 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
3065 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
3066 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
3068 // Glyph of Swiftmend
3069 if (!caster
->HasAura(54824))
3070 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
3072 addhealth
+= tickheal
* tickcount
;
3075 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
3077 m_healing
+= addhealth
;
3080 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
&& m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000100))
3082 // check for Riptide
3083 if (unitTarget
!= m_targets
.getUnitTarget())
3085 Aura
* riptide
= unitTarget
->GetAura(SPELL_AURA_PERIODIC_HEAL
, SPELLFAMILY_SHAMAN
, 0, 0x00000010, caster
->GetGUID());
3088 m_healing
+= m_healing
/4;
3089 unitTarget
->RemoveAura(riptide
);
3094 void Spell::EffectHealPct(SpellEffectIndex
/*eff_idx*/)
3096 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
3098 // Try to get original caster
3099 Unit
*caster
= GetAffectiveCaster();
3103 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
3104 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
3105 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DAMAGE
, addhealth
, this);
3107 int32 gain
= caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
3108 unitTarget
->getHostileRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
3112 void Spell::EffectHealMechanical(SpellEffectIndex
/*eff_idx*/)
3114 // Mechanic creature type should be correctly checked by targetCreatureType field
3115 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
3117 // Try to get original caster
3118 Unit
*caster
= GetAffectiveCaster();
3122 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, damage
, HEAL
);
3123 caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
3127 void Spell::EffectHealthLeech(SpellEffectIndex eff_idx
)
3131 if (!unitTarget
->isAlive())
3137 sLog
.outDebug("HealthLeech :%i", damage
);
3139 uint32 curHealth
= unitTarget
->GetHealth();
3140 damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
);
3141 if ((int32
)curHealth
< damage
)
3144 float multiplier
= m_spellInfo
->EffectMultipleValue
[eff_idx
];
3146 if (Player
*modOwner
= m_caster
->GetSpellModOwner())
3147 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
3149 int32 heal
= int32(damage
*multiplier
);
3150 if (m_caster
->isAlive())
3152 heal
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, heal
, HEAL
);
3153 m_caster
->DealHeal(m_caster
, heal
, m_spellInfo
);
3157 void Spell::DoCreateItem(SpellEffectIndex eff_idx
, uint32 itemtype
)
3159 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3162 Player
* player
= (Player
*)unitTarget
;
3164 uint32 newitemid
= itemtype
;
3165 ItemPrototype
const *pProto
= ObjectMgr::GetItemPrototype( newitemid
);
3168 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
3172 // bg reward have some special in code work
3174 switch(m_spellInfo
->Id
)
3176 case SPELL_AV_MARK_WINNER
:
3177 case SPELL_AV_MARK_LOSER
:
3178 bgType
= BATTLEGROUND_AV
;
3180 case SPELL_WS_MARK_WINNER
:
3181 case SPELL_WS_MARK_LOSER
:
3182 bgType
= BATTLEGROUND_WS
;
3184 case SPELL_AB_MARK_WINNER
:
3185 case SPELL_AB_MARK_LOSER
:
3186 bgType
= BATTLEGROUND_AB
;
3194 // TODO: maybe all this can be replaced by using correct calculated `damage` value
3195 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
3197 int32 basePoints
= m_currentBasePoints
[eff_idx
];
3198 int32 randomPoints
= m_spellInfo
->EffectDieSides
[eff_idx
];
3200 num_to_add
= basePoints
+ irand(1, randomPoints
);
3202 num_to_add
= basePoints
+ 1;
3204 else if (pProto
->MaxCount
== 1)
3206 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
3208 int32 basePoints
= m_currentBasePoints
[eff_idx
];
3209 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[eff_idx
];
3210 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
3217 if (num_to_add
> pProto
->GetMaxStackSize())
3218 num_to_add
= pProto
->GetMaxStackSize();
3220 // init items_count to 1, since 1 item will be created regardless of specialization
3222 // the chance to create additional items
3223 float additionalCreateChance
=0.0f
;
3224 // the maximum number of created additional items
3225 uint8 additionalMaxNum
=0;
3226 // get the chance and maximum number for creating extra items
3227 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
3229 // roll with this chance till we roll not to create or we create the max num
3230 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
3234 // really will be created more items
3235 num_to_add
*= items_count
;
3237 // can the player store the new item?
3238 ItemPosCountVec dest
;
3239 uint32 no_space
= 0;
3240 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
3241 if( msg
!= EQUIP_ERR_OK
)
3243 // convert to possible store amount
3244 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
3245 num_to_add
-= no_space
;
3248 // ignore mana gem case (next effect will recharge existed example)
3249 if (eff_idx
== EFFECT_INDEX_0
&& m_spellInfo
->Effect
[EFFECT_INDEX_1
] == SPELL_EFFECT_DUMMY
)
3252 // if not created by another reason from full inventory or unique items amount limitation
3253 player
->SendEquipError( msg
, NULL
, NULL
, newitemid
);
3260 // create the new item and store it
3261 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
3263 // was it successful? return error if not
3266 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
3270 // set the "Crafted by ..." property of the item
3271 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
3272 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
, player
->GetGUIDLow());
3274 // send info to the client
3276 player
->SendNewItem(pItem
, num_to_add
, true, bgType
== 0);
3278 // we succeeded in creating at least one item, so a levelup is possible
3280 player
->UpdateCraftSkill(m_spellInfo
->Id
);
3283 // for battleground marks send by mail if not add all expected
3284 if(no_space
> 0 && bgType
)
3286 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BattleGroundTypeId(bgType
)))
3287 bg
->SendRewardMarkByMail(player
, newitemid
, no_space
);
3291 void Spell::EffectCreateItem(SpellEffectIndex eff_idx
)
3293 DoCreateItem(eff_idx
,m_spellInfo
->EffectItemType
[eff_idx
]);
3296 void Spell::EffectCreateItem2(SpellEffectIndex eff_idx
)
3298 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
3300 Player
* player
= (Player
*)m_caster
;
3302 uint32 item_id
= m_spellInfo
->EffectItemType
[eff_idx
];
3304 DoCreateItem(eff_idx
, item_id
);
3306 // special case: fake item replaced by generate using spell_loot_template
3307 if (IsLootCraftingSpell(m_spellInfo
))
3309 if (!player
->HasItemCount(item_id
, 1))
3314 player
->DestroyItemCount(item_id
, count
, true);
3316 // create some random items
3317 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
3321 void Spell::EffectCreateRandomItem(SpellEffectIndex
/*eff_idx*/)
3323 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
3325 Player
* player
= (Player
*)m_caster
;
3327 // create some random items
3328 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
3331 void Spell::EffectPersistentAA(SpellEffectIndex eff_idx
)
3333 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
3335 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
3336 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
3338 int32 duration
= GetSpellDuration(m_spellInfo
);
3339 DynamicObject
* dynObj
= new DynamicObject
;
3340 if (!dynObj
->Create(m_caster
->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, eff_idx
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, radius
))
3345 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3346 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
3347 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
3348 m_caster
->AddDynObject(dynObj
);
3349 m_caster
->GetMap()->Add(dynObj
);
3352 void Spell::EffectEnergize(SpellEffectIndex eff_idx
)
3356 if(!unitTarget
->isAlive())
3359 if(m_spellInfo
->EffectMiscValue
[eff_idx
] < 0 || m_spellInfo
->EffectMiscValue
[eff_idx
] >= MAX_POWERS
)
3362 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[eff_idx
]);
3364 // Some level depends spells
3365 int level_multiplier
= 0;
3367 switch (m_spellInfo
->Id
)
3369 case 9512: // Restore Energy
3370 level_diff
= m_caster
->getLevel() - 40;
3371 level_multiplier
= 2;
3373 case 24571: // Blood Fury
3374 level_diff
= m_caster
->getLevel() - 60;
3375 level_multiplier
= 10;
3377 case 24532: // Burst of Energy
3378 level_diff
= m_caster
->getLevel() - 60;
3379 level_multiplier
= 4;
3381 case 31930: // Judgements of the Wise
3382 case 48542: // Revitalize (mana restore case)
3383 case 63375: // Improved Stormstrike
3384 case 68082: // Glyph of Seal of Command
3385 damage
= damage
* unitTarget
->GetCreateMana() / 100;
3392 damage
-= level_multiplier
* level_diff
;
3397 if(unitTarget
->GetMaxPower(power
) == 0)
3400 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, damage
, power
);
3402 // Mad Alchemist's Potion
3403 if (m_spellInfo
->Id
== 45051)
3405 // find elixirs on target
3406 uint32 elixir_mask
= 0;
3407 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
3408 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
3410 uint32 spell_id
= itr
->second
->GetId();
3411 if(uint32 mask
= sSpellMgr
.GetSpellElixirMask(spell_id
))
3412 elixir_mask
|= mask
;
3415 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3416 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
3418 // get all available elixirs by mask and spell level
3419 std::vector
<uint32
> elixirs
;
3420 SpellElixirMap
const& m_spellElixirs
= sSpellMgr
.GetSpellElixirMap();
3421 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
3423 if (itr
->second
& elixir_mask
)
3425 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
3428 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
3429 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
3432 elixirs
.push_back(itr
->first
);
3436 if (!elixirs
.empty())
3438 // cast random elixir on target
3439 uint32 rand_spell
= urand(0,elixirs
.size()-1);
3440 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
3445 void Spell::EffectEnergisePct(SpellEffectIndex eff_idx
)
3449 if (!unitTarget
->isAlive())
3452 if (m_spellInfo
->EffectMiscValue
[eff_idx
] < 0 || m_spellInfo
->EffectMiscValue
[eff_idx
] >= MAX_POWERS
)
3455 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[eff_idx
]);
3457 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
3461 uint32 gain
= damage
* maxPower
/ 100;
3462 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, gain
, power
);
3465 void Spell::SendLoot(uint64 guid
, LootType loottype
)
3469 switch (gameObjTarget
->GetGoType())
3471 case GAMEOBJECT_TYPE_DOOR
:
3472 case GAMEOBJECT_TYPE_BUTTON
:
3473 case GAMEOBJECT_TYPE_QUESTGIVER
:
3474 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
3475 case GAMEOBJECT_TYPE_GOOBER
:
3476 gameObjTarget
->Use(m_caster
);
3479 case GAMEOBJECT_TYPE_CHEST
:
3480 gameObjTarget
->Use(m_caster
);
3481 // Don't return, let loots been taken
3485 sLog
.outError("Spell::SendLoot unhandled GameObject type %u (entry %u).", gameObjTarget
->GetGoType(), gameObjTarget
->GetEntry());
3490 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3494 ((Player
*)m_caster
)->SendLoot(guid
, loottype
);
3497 void Spell::EffectOpenLock(SpellEffectIndex eff_idx
)
3499 if (!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
3501 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
3505 Player
* player
= (Player
*)m_caster
;
3513 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
3514 // Arathi Basin banner opening !
3515 if (goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
3516 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
3518 //CanUseBattleGroundObject() already called in CheckCast()
3519 // in battleground check
3520 if (BattleGround
*bg
= player
->GetBattleGround())
3522 // check if it's correct bg
3523 if (bg
->GetTypeID() == BATTLEGROUND_AB
|| bg
->GetTypeID() == BATTLEGROUND_AV
)
3524 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3528 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
3530 //CanUseBattleGroundObject() already called in CheckCast()
3531 // in battleground check
3532 if (BattleGround
*bg
= player
->GetBattleGround())
3534 if (bg
->GetTypeID() == BATTLEGROUND_EY
)
3535 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3539 lockId
= goInfo
->GetLockId();
3540 guid
= gameObjTarget
->GetGUID();
3542 else if (itemTarget
)
3544 lockId
= itemTarget
->GetProto()->LockID
;
3545 guid
= itemTarget
->GetGUID();
3549 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3553 SkillType skillId
= SKILL_NONE
;
3554 int32 reqSkillValue
= 0;
3557 SpellCastResult res
= CanOpenLock(eff_idx
, lockId
, skillId
, reqSkillValue
, skillValue
);
3558 if (res
!= SPELL_CAST_OK
)
3560 SendCastResult(res
);
3564 SendLoot(guid
, LOOT_SKINNING
);
3566 // not allow use skill grow at item base open
3567 if (!m_CastItem
&& skillId
!= SKILL_NONE
)
3569 // update skill if really known
3570 if (uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3574 // Allow one skill-up until respawned
3575 if (!gameObjTarget
->IsInSkillupList(player
->GetGUIDLow()) &&
3576 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
))
3577 gameObjTarget
->AddToSkillupList(player
->GetGUIDLow());
3579 else if (itemTarget
)
3582 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3588 void Spell::EffectSummonChangeItem(SpellEffectIndex eff_idx
)
3590 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3593 Player
*player
= (Player
*)m_caster
;
3595 // applied only to using item
3599 // ... only to item in own inventory/bank/equip_slot
3600 if (m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3603 uint32 newitemid
= m_spellInfo
->EffectItemType
[eff_idx
];
3607 uint16 pos
= m_CastItem
->GetPos();
3609 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3613 for(uint8 j
= PERM_ENCHANTMENT_SLOT
; j
<=TEMP_ENCHANTMENT_SLOT
; ++j
)
3615 if (m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)))
3616 pNewItem
->SetEnchantment(EnchantmentSlot(j
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(j
)));
3619 if (m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3621 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3622 player
->DurabilityLoss(pNewItem
, loosePercent
);
3625 if (player
->IsInventoryPos(pos
))
3627 ItemPosCountVec dest
;
3628 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3629 if (msg
== EQUIP_ERR_OK
)
3631 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3633 // prevent crash at access and unexpected charges counting with item update queue corrupt
3634 if (m_CastItem
==m_targets
.getItemTarget())
3635 m_targets
.setItemTarget(NULL
);
3639 player
->StoreItem( dest
, pNewItem
, true);
3643 else if (player
->IsBankPos (pos
))
3645 ItemPosCountVec dest
;
3646 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3647 if (msg
== EQUIP_ERR_OK
)
3649 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3651 // prevent crash at access and unexpected charges counting with item update queue corrupt
3652 if (m_CastItem
==m_targets
.getItemTarget())
3653 m_targets
.setItemTarget(NULL
);
3657 player
->BankItem( dest
, pNewItem
, true);
3661 else if (player
->IsEquipmentPos (pos
))
3664 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3665 if (msg
== EQUIP_ERR_OK
)
3667 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3669 // prevent crash at access and unexpected charges counting with item update queue corrupt
3670 if (m_CastItem
==m_targets
.getItemTarget())
3671 m_targets
.setItemTarget(NULL
);
3675 player
->EquipItem( dest
, pNewItem
, true);
3676 player
->AutoUnequipOffhandIfNeed();
3685 void Spell::EffectProficiency(SpellEffectIndex
/*eff_idx*/)
3687 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3689 Player
*p_target
= (Player
*)unitTarget
;
3691 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3692 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_WEAPON
&& !(p_target
->GetWeaponProficiency() & subClassMask
))
3694 p_target
->AddWeaponProficiency(subClassMask
);
3695 p_target
->SendProficiency(ITEM_CLASS_WEAPON
, p_target
->GetWeaponProficiency());
3697 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_ARMOR
&& !(p_target
->GetArmorProficiency() & subClassMask
))
3699 p_target
->AddArmorProficiency(subClassMask
);
3700 p_target
->SendProficiency(ITEM_CLASS_ARMOR
, p_target
->GetArmorProficiency());
3704 void Spell::EffectApplyAreaAura(SpellEffectIndex eff_idx
)
3708 if (!unitTarget
->isAlive())
3711 AreaAura
* Aur
= new AreaAura(m_spellInfo
, eff_idx
, &m_currentBasePoints
[eff_idx
], unitTarget
, m_caster
, m_CastItem
);
3712 unitTarget
->AddAura(Aur
);
3715 void Spell::EffectSummonType(SpellEffectIndex eff_idx
)
3717 uint32 prop_id
= m_spellInfo
->EffectMiscValueB
[eff_idx
];
3718 SummonPropertiesEntry
const *summon_prop
= sSummonPropertiesStore
.LookupEntry(prop_id
);
3721 sLog
.outError("EffectSummonType: Unhandled summon type %u", prop_id
);
3725 switch(summon_prop
->Group
)
3727 // faction handled later on, or loaded from template
3728 case SUMMON_PROP_GROUP_WILD
:
3729 case SUMMON_PROP_GROUP_FRIENDLY
:
3731 switch(summon_prop
->Type
)
3733 case SUMMON_PROP_TYPE_OTHER
:
3735 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3736 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3737 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3738 if(prop_id
== 121 || prop_id
== 647)
3739 DoSummonTotem(eff_idx
);
3741 DoSummonWild(eff_idx
, summon_prop
->FactionId
);
3744 case SUMMON_PROP_TYPE_SUMMON
:
3745 case SUMMON_PROP_TYPE_GUARDIAN
:
3746 case SUMMON_PROP_TYPE_ARMY
:
3747 case SUMMON_PROP_TYPE_DK
:
3748 case SUMMON_PROP_TYPE_CONSTRUCT
:
3750 // JC golems - 32804, etc -- fits much better totem AI
3751 if(m_spellInfo
->SpellIconID
== 2056)
3752 DoSummonTotem(eff_idx
);
3753 if(prop_id
== 832) // scrapbot
3754 DoSummonWild(eff_idx
, summon_prop
->FactionId
);
3756 DoSummonGuardian(eff_idx
, summon_prop
->FactionId
);
3759 case SUMMON_PROP_TYPE_TOTEM
:
3760 DoSummonTotem(eff_idx
, summon_prop
->Slot
);
3762 case SUMMON_PROP_TYPE_CRITTER
:
3763 DoSummonCritter(eff_idx
, summon_prop
->FactionId
);
3765 case SUMMON_PROP_TYPE_PHASING
:
3766 case SUMMON_PROP_TYPE_LIGHTWELL
:
3767 case SUMMON_PROP_TYPE_REPAIR_BOT
:
3768 DoSummonWild(eff_idx
, summon_prop
->FactionId
);
3770 case SUMMON_PROP_TYPE_SIEGE_VEH
:
3771 case SUMMON_PROP_TYPE_DRAKE_VEH
:
3773 // EffectSummonVehicle(i);
3776 sLog
.outError("EffectSummonType: Unhandled summon type %u", summon_prop
->Type
);
3781 case SUMMON_PROP_GROUP_PETS
:
3783 // FIXME : multiple summons - not yet supported as pet
3784 //1562 - force of nature - sid 33831
3785 //1161 - feral spirit - sid 51533
3786 if(prop_id
== 1562) // 3 uncontrolable instead of one controllable :/
3787 DoSummonGuardian(eff_idx
, summon_prop
->FactionId
);
3792 case SUMMON_PROP_GROUP_CONTROLLABLE
:
3795 // maybe wrong - but thats the handler currently used for those
3796 DoSummonGuardian(eff_idx
, summon_prop
->FactionId
);
3799 case SUMMON_PROP_GROUP_VEHICLE
:
3802 // EffectSummonVehicle(i);
3806 sLog
.outError("EffectSummonType: Unhandled summon group type %u", summon_prop
->Group
);
3811 void Spell::DoSummon(SpellEffectIndex eff_idx
)
3813 if (m_caster
->GetPetGUID())
3818 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[eff_idx
];
3821 uint32 level
= m_caster
->getLevel();
3822 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3824 int32 duration
= GetSpellDuration(m_spellInfo
);
3825 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
3826 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
3828 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3830 // Summon in dest location
3832 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3834 x
= m_targets
.m_destX
;
3835 y
= m_targets
.m_destY
;
3836 z
= m_targets
.m_destZ
;
3837 spawnCreature
->Relocate(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, -m_caster
->GetOrientation());
3840 // set timer for unsummon
3842 spawnCreature
->SetDuration(duration
);
3847 Map
*map
= m_caster
->GetMap();
3848 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
3849 if (!spawnCreature
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
3850 m_spellInfo
->EffectMiscValue
[eff_idx
], pet_number
))
3852 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[eff_idx
]);
3853 delete spawnCreature
;
3857 // Summon in dest location
3859 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3861 x
= m_targets
.m_destX
;
3862 y
= m_targets
.m_destY
;
3863 z
= m_targets
.m_destZ
;
3866 m_caster
->GetClosePoint(x
, y
, z
, spawnCreature
->GetObjectSize());
3868 spawnCreature
->Relocate(x
, y
, z
, -m_caster
->GetOrientation());
3869 spawnCreature
->SetSummonPoint(x
, y
, z
, -m_caster
->GetOrientation());
3871 if (!spawnCreature
->IsPositionValid())
3873 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3874 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3875 delete spawnCreature
;
3879 // set timer for unsummon
3881 spawnCreature
->SetDuration(duration
);
3883 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3884 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
3885 spawnCreature
->setPowerType(POWER_MANA
);
3886 spawnCreature
->setFaction(m_caster
->getFaction());
3887 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3888 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3889 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3890 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3891 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3892 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3893 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3894 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3896 spawnCreature
->InitStatsForLevel(level
, m_caster
);
3898 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3900 spawnCreature
->UpdateWalkMode(m_caster
);
3902 spawnCreature
->AIM_Initialize();
3903 spawnCreature
->InitPetCreateSpells();
3904 spawnCreature
->InitLevelupSpellsForLevel();
3905 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3906 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3908 std::string name
= m_caster
->GetName();
3909 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3910 spawnCreature
->SetName( name
);
3912 map
->Add((Creature
*)spawnCreature
);
3914 m_caster
->SetPet(spawnCreature
);
3916 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3918 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3919 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3920 ((Player
*)m_caster
)->PetSpellInitialize();
3923 if (m_caster
->GetTypeId() == TYPEID_UNIT
&& ((Creature
*)m_caster
)->AI())
3924 ((Creature
*)m_caster
)->AI()->JustSummoned((Creature
*)spawnCreature
);
3927 void Spell::EffectLearnSpell(SpellEffectIndex eff_idx
)
3932 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3934 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3935 EffectLearnPetSpell(eff_idx
);
3940 Player
*player
= (Player
*)unitTarget
;
3942 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[eff_idx
];
3943 player
->learnSpell(spellToLearn
,false);
3945 sLog
.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3948 void Spell::EffectDispel(SpellEffectIndex eff_idx
)
3953 // Fill possible dispell list
3954 std::vector
<Aura
*> dispel_list
;
3956 // Create dispel mask by dispel type
3957 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[eff_idx
];
3958 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3959 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3960 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3962 Aura
*aur
= (*itr
).second
;
3963 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3965 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3967 bool positive
= true;
3968 if (!aur
->IsPositive())
3971 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3973 // do not remove positive auras if friendly target
3974 // negative auras if non-friendly target
3975 if (positive
== unitTarget
->IsFriendlyTo(m_caster
))
3978 // Add aura to dispel list (all stack cases)
3979 for(int k
= 0; k
< aur
->GetStackAmount(); ++k
)
3980 dispel_list
.push_back(aur
);
3983 // Ok if exist some buffs for dispel try dispel it
3984 if (!dispel_list
.empty())
3986 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3987 std::list
< uint32
> fail_list
; // spell_id
3989 // some spells have effect value = 0 and all from its by meaning expect 1
3993 // Dispell N = damage buffs (or while exist buffs for dispel)
3994 for (int32 count
=0; count
< damage
&& !dispel_list
.empty(); ++count
)
3996 // Random select buff for dispel
3997 std::vector
<Aura
*>::iterator dispel_itr
= dispel_list
.begin();
3998 std::advance(dispel_itr
,urand(0, dispel_list
.size()-1));
4000 Aura
*aur
= *dispel_itr
;
4002 // remove entry from dispel_list
4003 dispel_list
.erase(dispel_itr
);
4005 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
4006 // Base dispel chance
4007 // TODO: possible chance depend from spell level??
4008 int32 miss_chance
= 0;
4009 // Apply dispel mod from aura caster
4010 if (Unit
*caster
= aur
->GetCaster())
4012 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
4013 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
4016 if (roll_chance_i(miss_chance
))
4017 fail_list
.push_back(spellInfo
->Id
);
4019 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
4021 // Send success log and really remove auras
4022 if (!success_list
.empty())
4024 int32 count
= success_list
.size();
4025 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
4026 data
<< unitTarget
->GetPackGUID(); // Victim GUID
4027 data
<< m_caster
->GetPackGUID(); // Caster GUID
4028 data
<< uint32(m_spellInfo
->Id
); // Dispel spell id
4029 data
<< uint8(0); // not used
4030 data
<< uint32(count
); // count
4031 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
4033 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
4034 data
<< uint32(spellInfo
->Id
); // Spell Id
4035 data
<< uint8(0); // 0 - dispeled !=0 cleansed
4036 unitTarget
->RemoveSingleAuraDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
4038 m_caster
->SendMessageToSet(&data
, true);
4040 // On success dispel
4042 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
4044 int32 heal_amount
= m_spellInfo
->CalculateSimpleValue(EFFECT_INDEX_1
);
4045 m_caster
->CastCustomSpell(m_caster
, 19658, &heal_amount
, NULL
, NULL
, true);
4048 // Send fail log to client
4049 if (!fail_list
.empty())
4051 // Failed to dispell
4052 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
4053 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
4054 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
4055 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
4056 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
4057 data
<< uint32(*j
); // Spell Id
4058 m_caster
->SendMessageToSet(&data
, true);
4063 void Spell::EffectDualWield(SpellEffectIndex
/*eff_idx*/)
4065 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4066 ((Player
*)unitTarget
)->SetCanDualWield(true);
4069 void Spell::EffectPull(SpellEffectIndex
/*eff_idx*/)
4071 // TODO: create a proper pull towards distract spell center for distract
4072 sLog
.outDebug("WORLD: Spell Effect DUMMY");
4075 void Spell::EffectDistract(SpellEffectIndex
/*eff_idx*/)
4077 // Check for possible target
4078 if (!unitTarget
|| unitTarget
->isInCombat())
4081 // target must be OK to do this
4082 if( unitTarget
->hasUnitState(UNIT_STAT_CAN_NOT_REACT
) )
4085 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
4087 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4089 // For players just turn them
4091 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
4092 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
4093 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
4097 // Set creature Distracted, Stop it, And turn it
4098 unitTarget
->SetOrientation(angle
);
4099 unitTarget
->StopMoving();
4100 unitTarget
->GetMotionMaster()->MoveDistract(damage
* IN_MILLISECONDS
);
4104 void Spell::EffectPickPocket(SpellEffectIndex
/*eff_idx*/)
4106 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4109 // victim must be creature and attackable
4110 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
))
4113 // victim have to be alive and humanoid or undead
4114 if (unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
4116 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
4118 if (chance
> irand(0, 19))
4120 // Stealing successful
4121 //sLog.outDebug("Sending loot from pickpocket");
4122 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
4126 // Reveal action + get attack
4127 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
4128 if (((Creature
*)unitTarget
)->AI())
4129 ((Creature
*)unitTarget
)->AI()->AttackedBy(m_caster
);
4134 void Spell::EffectAddFarsight(SpellEffectIndex eff_idx
)
4136 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4139 int32 duration
= GetSpellDuration(m_spellInfo
);
4140 DynamicObject
* dynObj
= new DynamicObject
;
4142 // set radius to 0: spell not expected to work as persistent aura
4143 if(!dynObj
->Create(m_caster
->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, eff_idx
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, 0))
4148 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
4149 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
4150 m_caster
->AddDynObject(dynObj
);
4151 m_caster
->GetMap()->Add(dynObj
);
4152 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
4155 void Spell::DoSummonWild(SpellEffectIndex eff_idx
, uint32 forceFaction
)
4157 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4158 if (!creature_entry
)
4161 uint32 level
= m_caster
->getLevel();
4163 // level of creature summoned using engineering item based at engineering skill level
4164 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
4166 ItemPrototype
const *proto
= m_CastItem
->GetProto();
4167 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
4169 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
4175 // select center of summon position
4176 float center_x
= m_targets
.m_destX
;
4177 float center_y
= m_targets
.m_destY
;
4178 float center_z
= m_targets
.m_destZ
;
4180 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
4181 int32 duration
= GetSpellDuration(m_spellInfo
);
4182 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
4184 int32 amount
= damage
> 0 ? damage
: 1;
4186 for(int32 count
= 0; count
< amount
; ++count
)
4189 // If dest location if present
4190 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4192 // Summon 1 unit in dest location
4195 px
= m_targets
.m_destX
;
4196 py
= m_targets
.m_destY
;
4197 pz
= m_targets
.m_destZ
;
4199 // Summon in random point all other units if location present
4201 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
4203 // Summon if dest location not present near caster
4205 m_caster
->GetClosePoint(px
, py
, pz
, 3.0f
);
4207 if(Creature
*summon
= m_caster
->SummonCreature(creature_entry
, px
, py
, pz
, m_caster
->GetOrientation(), summonType
, duration
))
4209 summon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4210 summon
->SetCreatorGUID(m_caster
->GetGUID());
4213 summon
->setFaction(forceFaction
);
4218 void Spell::DoSummonGuardian(SpellEffectIndex eff_idx
, uint32 forceFaction
)
4220 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4224 // in another case summon new
4225 uint32 level
= m_caster
->getLevel();
4227 // level of pet summoned using engineering item based at engineering skill level
4228 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& m_CastItem
)
4230 ItemPrototype
const *proto
= m_CastItem
->GetProto();
4231 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
4233 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
4236 level
= skill202
/ 5;
4241 // select center of summon position
4242 float center_x
= m_targets
.m_destX
;
4243 float center_y
= m_targets
.m_destY
;
4244 float center_z
= m_targets
.m_destZ
;
4246 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
4247 int32 duration
= GetSpellDuration(m_spellInfo
);
4248 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
4249 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
4251 int32 amount
= damage
> 0 ? damage
: 1;
4253 for(int32 count
= 0; count
< amount
; ++count
)
4255 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
4257 Map
*map
= m_caster
->GetMap();
4258 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
4259 if (!spawnCreature
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
4260 m_spellInfo
->EffectMiscValue
[eff_idx
], pet_number
))
4262 sLog
.outError("no such creature entry %u", m_spellInfo
->EffectMiscValue
[eff_idx
]);
4263 delete spawnCreature
;
4268 // If dest location if present
4269 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4271 // Summon 1 unit in dest location
4274 px
= m_targets
.m_destX
;
4275 py
= m_targets
.m_destY
;
4276 pz
= m_targets
.m_destZ
;
4278 // Summon in random point all other units if location present
4280 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
4282 // Summon if dest location not present near caster
4284 m_caster
->GetClosePoint(px
, py
, pz
,spawnCreature
->GetObjectSize());
4286 spawnCreature
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4287 spawnCreature
->SetSummonPoint(px
, py
, pz
, m_caster
->GetOrientation());
4289 if (!spawnCreature
->IsPositionValid())
4291 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
4292 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
4293 delete spawnCreature
;
4298 spawnCreature
->SetDuration(duration
);
4300 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
4301 spawnCreature
->setPowerType(POWER_MANA
);
4302 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, spawnCreature
->GetCreatureInfo()->npcflag
);
4303 spawnCreature
->setFaction(forceFaction
? forceFaction
: m_caster
->getFaction());
4304 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
4305 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4306 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
4307 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
4308 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4310 spawnCreature
->InitStatsForLevel(level
, m_caster
);
4311 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
4313 spawnCreature
->AIM_Initialize();
4315 m_caster
->AddGuardian(spawnCreature
);
4317 map
->Add((Creature
*)spawnCreature
);
4321 void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx
)
4326 if (unitTarget
->isInFlight())
4329 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
4332 m_caster
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
4334 unitTarget
->NearTeleportTo(fx
, fy
, fz
, -m_caster
->GetOrientation(), unitTarget
==m_caster
);
4337 void Spell::EffectLearnSkill(SpellEffectIndex eff_idx
)
4339 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4345 uint32 skillid
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4346 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
4347 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
? skillval
: 1, damage
* 75);
4350 void Spell::EffectAddHonor(SpellEffectIndex
/*eff_idx*/)
4352 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4355 // not scale value for item based reward (/10 value expected)
4358 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, float(damage
/ 10));
4359 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo
->Id
, damage
/10, m_CastItem
->GetEntry(),((Player
*)unitTarget
)->GetGUIDLow());
4363 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4366 float honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
4367 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
4368 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %f honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
4372 //maybe we have correct honor_gain in damage already
4373 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, (float)damage
);
4374 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
4378 void Spell::EffectTradeSkill(SpellEffectIndex
/*eff_idx*/)
4380 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4382 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4383 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4384 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4387 void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx
)
4389 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4394 Player
* p_caster
= (Player
*)m_caster
;
4396 // not grow at item use at item case
4397 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
4399 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4403 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4407 // item can be in trade slot and have owner diff. from caster
4408 Player
* item_owner
= itemTarget
->GetOwner();
4412 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
) )
4414 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4415 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4416 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4417 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4420 // remove old enchanting before applying new if equipped
4421 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
4423 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
4425 // add new enchanting if equipped
4426 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
4428 // update trade window for show enchantment for caster in trade window
4429 if (m_targets
.m_targetMask
& TARGET_FLAG_TRADE_ITEM
)
4430 p_caster
->GetSession()->SendUpdateTrade();
4433 void Spell::EffectEnchantItemPrismatic(SpellEffectIndex eff_idx
)
4435 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4440 Player
* p_caster
= (Player
*)m_caster
;
4442 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4446 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4450 // support only enchantings with add socket in this slot
4452 bool add_socket
= false;
4453 for(int i
= 0; i
< 3; ++i
)
4455 if (pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
4463 sLog
.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not suppoted yet.",
4464 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
4469 // item can be in trade slot and have owner diff. from caster
4470 Player
* item_owner
= itemTarget
->GetOwner();
4474 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
) )
4476 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4477 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4478 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4479 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4482 // remove old enchanting before applying new if equipped
4483 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
4485 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
4487 // add new enchanting if equipped
4488 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
4490 // update trade window for show enchantment for caster in trade window
4491 if (m_targets
.m_targetMask
& TARGET_FLAG_TRADE_ITEM
)
4492 p_caster
->GetSession()->SendUpdateTrade();
4495 void Spell::EffectEnchantItemTmp(SpellEffectIndex eff_idx
)
4497 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4500 Player
* p_caster
= (Player
*)m_caster
;
4502 // Rockbiter Weapon apply to both weapon
4503 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
&& m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000400000))
4505 uint32 spell_id
= 0;
4507 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4508 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4509 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4513 case 2: spell_id
= 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4515 case 4: spell_id
= 36753; break; // 0% [ 7% == 4, 14% == 4]
4516 case 5: spell_id
= 36751; break; // 20%
4518 case 6: spell_id
= 36754; break; // 0% [ 7% == 6, 14% == 6]
4519 case 7: spell_id
= 36755; break; // 20%
4521 case 9: spell_id
= 36761; break; // 0% [ 7% == 6]
4522 case 10: spell_id
= 36758; break; // 14%
4523 case 11: spell_id
= 36760; break; // 20%
4525 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage
);
4530 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spell_id
);
4533 sLog
.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id
);
4537 for(int j
= BASE_ATTACK
; j
<= OFF_ATTACK
; ++j
)
4539 if (Item
* item
= p_caster
->GetWeaponForAttack(WeaponAttackType(j
)))
4541 if (item
->IsFitToSpellRequirements(m_spellInfo
))
4543 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
4544 SpellCastTargets targets
;
4545 targets
.setItemTarget( item
);
4546 spell
->prepare(&targets
);
4556 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4560 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,eff_idx
);
4564 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4567 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,eff_idx
,enchant_id
);
4571 // select enchantment duration
4574 // rogue family enchantments exception by duration
4575 if(m_spellInfo
->Id
== 38615) // Poison
4576 duration
= 1800; // 30 mins
4577 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4578 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
4579 duration
= 3600; // 1 hour
4580 // shaman family enchantments
4581 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
4582 duration
= 1800; // 30 mins
4583 // other cases with this SpellVisual already selected
4584 else if(m_spellInfo
->SpellVisual
[0] == 215)
4585 duration
= 1800; // 30 mins
4586 // some fishing pole bonuses
4587 else if(m_spellInfo
->SpellVisual
[0] == 563)
4588 duration
= 600; // 10 mins
4589 // shaman rockbiter enchantments
4590 else if(m_spellInfo
->SpellVisual
[0] == 0)
4591 duration
= 1800; // 30 mins
4592 else if(m_spellInfo
->Id
== 29702) // Greater Ward of Shielding
4593 duration
= 300; // 5 mins
4594 else if(m_spellInfo
->Id
== 37360) // Consecrated Weapon
4595 duration
= 300; // 5 mins
4598 duration
= 3600; // 1 hour
4600 // item can be in trade slot and have owner diff. from caster
4601 Player
* item_owner
= itemTarget
->GetOwner();
4605 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
) )
4607 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4608 p_caster
->GetName(), p_caster
->GetSession()->GetAccountId(),
4609 itemTarget
->GetProto()->Name1
, itemTarget
->GetEntry(),
4610 item_owner
->GetName(), item_owner
->GetSession()->GetAccountId());
4613 // remove old enchanting before applying new if equipped
4614 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
, false);
4616 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
* 1000, 0);
4618 // add new enchanting if equipped
4619 item_owner
->ApplyEnchantment(itemTarget
, TEMP_ENCHANTMENT_SLOT
, true);
4621 // update trade window for show enchantment for caster in trade window
4622 if (m_targets
.m_targetMask
& TARGET_FLAG_TRADE_ITEM
)
4623 p_caster
->GetSession()->SendUpdateTrade();
4626 void Spell::EffectTameCreature(SpellEffectIndex
/*eff_idx*/)
4628 // Caster must be player, checked in Spell::CheckCast
4629 // Spell can be triggered, we need to check original caster prior to caster
4630 Player
* plr
= (Player
*)GetAffectiveCaster();
4632 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4634 // cast finish successfully
4635 //SendChannelUpdate(0);
4638 Pet
* pet
= plr
->CreateTamedPetFrom(creatureTarget
, m_spellInfo
->Id
);
4639 if(!pet
) // in versy specific state like near world end/etc.
4642 // "kill" original creature
4643 creatureTarget
->ForcedDespawn();
4645 uint32 level
= (creatureTarget
->getLevel() < (plr
->getLevel() - 5)) ? (plr
->getLevel() - 5) : creatureTarget
->getLevel();
4647 // prepare visual effect for levelup
4648 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4651 pet
->GetMap()->Add((Creature
*)pet
);
4653 // visual effect for levelup
4654 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4656 // caster have pet now
4659 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4660 plr
->PetSpellInitialize();
4663 void Spell::EffectSummonPet(SpellEffectIndex eff_idx
)
4665 uint32 petentry
= m_spellInfo
->EffectMiscValue
[eff_idx
];
4667 Pet
*OldSummon
= m_caster
->GetPet();
4669 // if pet requested type already exist
4672 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4674 // pet in corpse state can't be summoned
4675 if( OldSummon
->isDead() )
4678 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4681 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4683 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4684 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4686 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4688 ((Player
*)m_caster
)->PetSpellInitialize();
4693 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4694 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4699 Pet
* NewSummon
= new Pet
;
4701 // petentry==0 for hunter "call pet" (current pet summoned if any)
4702 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
, petentry
))
4704 if(NewSummon
->getPetType() == SUMMON_PET
)
4706 // Remove Demonic Sacrifice auras (known pet)
4707 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4708 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin(); itr
!= auraClassScripts
.end();)
4710 if((*itr
)->GetModifier()->m_miscvalue
== 2228)
4712 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4713 itr
= auraClassScripts
.begin();
4723 // not error in case fail hunter call pet
4730 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4734 sLog
.outError("EffectSummonPet: creature entry %u not found.", petentry
);
4739 Map
*map
= m_caster
->GetMap();
4740 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
4741 if(!NewSummon
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4742 petentry
, pet_number
))
4749 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4751 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4753 if(!NewSummon
->IsPositionValid())
4755 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4756 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4761 uint32 petlevel
= m_caster
->getLevel();
4762 NewSummon
->setPetType(SUMMON_PET
);
4764 uint32 faction
= m_caster
->getFaction();
4765 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4767 if ( ((Creature
*)m_caster
)->isTotem() )
4768 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4770 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4773 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4774 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4775 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
4776 NewSummon
->setFaction(faction
);
4777 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4778 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4779 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, uint32(time(NULL
)));
4780 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4781 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4782 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4784 NewSummon
->UpdateWalkMode(m_caster
);
4786 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4787 // this enables pet details window (Shift+P)
4789 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4790 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4791 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
, UNIT_FLAG_PVP_ATTACKABLE
);
4793 if(m_caster
->IsPvP())
4794 NewSummon
->SetPvP(true);
4796 if(m_caster
->IsFFAPvP())
4797 NewSummon
->SetFFAPvP(true);
4799 NewSummon
->InitStatsForLevel(petlevel
, m_caster
);
4800 NewSummon
->InitPetCreateSpells();
4801 NewSummon
->InitLevelupSpellsForLevel();
4802 NewSummon
->InitTalentForLevel();
4804 if(NewSummon
->getPetType() == SUMMON_PET
)
4806 // Remove Demonic Sacrifice auras (new pet)
4807 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4808 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin(); itr
!= auraClassScripts
.end();)
4810 if((*itr
)->GetModifier()->m_miscvalue
== 2228)
4812 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4813 itr
= auraClassScripts
.begin();
4819 // generate new name for summon pet
4820 std::string new_name
= sObjectMgr
.GeneratePetName(petentry
);
4821 if(!new_name
.empty())
4822 NewSummon
->SetName(new_name
);
4824 else if(NewSummon
->getPetType() == HUNTER_PET
)
4826 NewSummon
->RemoveByteFlag(UNIT_FIELD_BYTES_2
, 2, UNIT_CAN_BE_RENAMED
);
4827 NewSummon
->SetByteFlag(UNIT_FIELD_BYTES_2
, 2, UNIT_CAN_BE_ABANDONED
);
4830 NewSummon
->AIM_Initialize();
4831 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4832 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4834 map
->Add((Creature
*)NewSummon
);
4836 m_caster
->SetPet(NewSummon
);
4837 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4839 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4841 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4842 ((Player
*)m_caster
)->PetSpellInitialize();
4846 void Spell::EffectLearnPetSpell(SpellEffectIndex eff_idx
)
4848 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4851 Player
*_player
= (Player
*)m_caster
;
4853 Pet
*pet
= _player
->GetPet();
4859 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[eff_idx
]);
4860 if(!learn_spellproto
)
4863 pet
->learnSpell(learn_spellproto
->Id
);
4865 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4866 _player
->PetSpellInitialize();
4869 void Spell::EffectTaunt(SpellEffectIndex
/*eff_idx*/)
4874 // this effect use before aura Taunt apply for prevent taunt already attacking target
4875 // for spell as marked "non effective at already attacking target"
4876 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4878 if (unitTarget
->getVictim()==m_caster
)
4880 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4885 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4886 if (unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4887 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4890 void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx
)
4894 if(!unitTarget
->isAlive())
4897 // multiple weapon dmg effect workaround
4898 // execute only the last weapon damage
4899 // and handle all effects at once
4900 for (int j
= 0; j
< MAX_EFFECT_INDEX
; ++j
)
4902 switch(m_spellInfo
->Effect
[j
])
4904 case SPELL_EFFECT_WEAPON_DAMAGE
:
4905 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4906 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4907 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4908 if (j
< int(eff_idx
)) // we must calculate only at last weapon effect
4914 // some spell specific modifiers
4915 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4917 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4918 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4919 bool normalized
= false;
4921 int32 spell_bonus
= 0; // bonus specific for spell
4922 switch(m_spellInfo
->SpellFamilyName
)
4924 case SPELLFAMILY_WARRIOR
:
4926 // Devastate bonus and sunder armor refresh
4927 if(m_spellInfo
->SpellVisual
[0] == 12295 && m_spellInfo
->SpellIconID
== 1508)
4930 // Need refresh all Sunder Armor auras from this caster
4931 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4932 SpellEntry
const *spellInfo
;
4933 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4935 spellInfo
= (*itr
).second
->GetSpellProto();
4936 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4937 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000)) &&
4938 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4940 (*itr
).second
->RefreshAura();
4941 stack
= (*itr
).second
->GetStackAmount();
4946 spell_bonus
+= stack
* CalculateDamage(EFFECT_INDEX_2
, unitTarget
);
4947 if (!stack
|| stack
< spellInfo
->StackAmount
)
4948 // Devastate causing Sunder Armor Effect
4949 // and no need to cast over max stack amount
4950 m_caster
->CastSpell(unitTarget
, 58567, true);
4954 case SPELLFAMILY_ROGUE
:
4956 // Mutilate (for each hand)
4957 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x600000000))
4961 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4966 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4967 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4969 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4978 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4981 else if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000)))
4983 Item
* weapon
= ((Player
*)m_caster
)->GetWeaponForAttack(m_attackType
,true,true);
4984 if (weapon
&& weapon
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_DAGGER
)
4985 totalDamagePercentMod
*= 1.5f
; // 150% to daggers
4989 case SPELLFAMILY_PALADIN
:
4991 // Judgement of Command - receive benefit from Spell Damage and Attack Power
4992 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00020000000000))
4994 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
4995 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
4996 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
4997 spell_bonus
+= int32(ap
* 0.08f
) + int32(holy
* 13 / 100);
5001 case SPELLFAMILY_HUNTER
:
5004 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x80000000000000))
5006 // 0.4*RAP added to damage (that is 0.2 if we apply PercentMod (200%) to spell_bonus, too)
5007 spellBonusNeedWeaponDamagePercentMod
= true;
5008 spell_bonus
+= int32( 0.2f
* m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
) );
5012 case SPELLFAMILY_SHAMAN
:
5014 // Skyshatter Harness item set bonus
5016 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x001000000000))
5018 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
5019 for(Unit::AuraList::const_iterator citr
= m_OverrideClassScript
.begin(); citr
!= m_OverrideClassScript
.end(); ++citr
)
5021 // Stormstrike AP Buff
5022 if ( (*citr
)->GetModifier()->m_miscvalue
== 5634 )
5024 m_caster
->CastSpell(m_caster
, 38430, true, NULL
, *citr
);
5031 case SPELLFAMILY_DEATHKNIGHT
:
5033 // Blood Strike, Heart Strike, Obliterate
5034 // Blood-Caked Strike, Scourge Strike
5035 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000001400000) ||
5036 m_spellInfo
->SpellIconID
== 1736 || m_spellInfo
->SpellIconID
== 3143)
5039 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
5040 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
5042 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
5043 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
5044 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
5050 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
5051 float bonus
= count
* CalculateDamage(m_spellInfo
->SpellIconID
== 1736 ? EFFECT_INDEX_0
: EFFECT_INDEX_2
, unitTarget
) / 100.0f
;
5052 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
5053 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000000400000) ||
5054 m_spellInfo
->SpellIconID
== 1736)
5057 totalDamagePercentMod
*= 1.0f
+ bonus
;
5060 // Heart Strike secondary target
5061 if (m_spellInfo
->SpellIconID
== 3145)
5062 if (m_targets
.getUnitTarget() != unitTarget
)
5063 weaponDamagePercentMod
/= 2.0f
;
5065 // Glyph of Blood Strike
5066 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000400000) &&
5067 m_caster
->HasAura(59332) &&
5068 unitTarget
->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED
))
5070 totalDamagePercentMod
*= 1.2f
; // 120% if snared
5072 // Glyph of Death Strike
5073 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000010) &&
5074 m_caster
->HasAura(59336))
5076 int32 rp
= m_caster
->GetPower(POWER_RUNIC_POWER
) / 10;
5079 totalDamagePercentMod
*= 1.0f
+ rp
/ 100.0f
;
5081 // Glyph of Plague Strike
5082 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000001) &&
5083 m_caster
->HasAura(58657) )
5085 totalDamagePercentMod
*= 1.2f
;
5091 int32 fixed_bonus
= 0;
5092 for (int j
= 0; j
< MAX_EFFECT_INDEX
; ++j
)
5094 switch(m_spellInfo
->Effect
[j
])
5096 case SPELL_EFFECT_WEAPON_DAMAGE
:
5097 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
5098 fixed_bonus
+= CalculateDamage(SpellEffectIndex(j
), unitTarget
);
5100 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
5101 fixed_bonus
+= CalculateDamage(SpellEffectIndex(j
), unitTarget
);
5104 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
5105 weaponDamagePercentMod
*= float(CalculateDamage(SpellEffectIndex(j
), unitTarget
)) / 100.0f
;
5107 // applied only to prev.effects fixed damage
5108 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
5111 break; // not weapon damage effect, just skip
5115 // apply weaponDamagePercentMod to spell bonus also
5116 if(spellBonusNeedWeaponDamagePercentMod
)
5117 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
5119 // non-weapon damage
5120 int32 bonus
= spell_bonus
+ fixed_bonus
;
5122 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
5126 switch(m_attackType
)
5129 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
5130 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
5131 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
5134 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
5135 bonus
= int32(bonus
*weapon_total_pct
);
5138 // + weapon damage with applied weapon% dmg to base weapon damage in call
5139 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
5142 bonus
= int32(bonus
*totalDamagePercentMod
);
5144 // prevent negative damage
5145 m_damage
+= uint32(bonus
> 0 ? bonus
: 0);
5148 if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x2000000)))
5150 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
5151 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
5154 else if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==UI64LIT(0x0000040000000000)))
5156 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
5157 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
5161 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5163 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack(RANGED_ATTACK
, true, false);
5165 // wands don't have ammo
5166 if (!pItem
|| pItem
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_WAND
)
5169 if (pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
5171 if(pItem
->GetMaxStackCount()==1)
5173 // decrease durability for non-stackable throw weapon
5174 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
5178 // decrease items amount for stackable throw weapon
5180 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
5183 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
5184 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
5188 void Spell::EffectThreat(SpellEffectIndex
/*eff_idx*/)
5190 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
5193 if(!unitTarget
->CanHaveThreatList())
5196 unitTarget
->AddThreat(m_caster
, float(damage
), false, GetSpellSchoolMask(m_spellInfo
), m_spellInfo
);
5199 void Spell::EffectHealMaxHealth(SpellEffectIndex
/*eff_idx*/)
5203 if(!unitTarget
->isAlive())
5206 uint32 heal
= m_caster
->GetMaxHealth();
5211 void Spell::EffectInterruptCast(SpellEffectIndex
/*eff_idx*/)
5215 if(!unitTarget
->isAlive())
5218 // TODO: not all spells that used this effect apply cooldown at school spells
5219 // also exist case: apply cooldown to interrupted cast only and to all spells
5220 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; ++i
)
5222 if (Spell
* spell
= unitTarget
->GetCurrentSpell(CurrentSpellTypes(i
)))
5224 SpellEntry
const* curSpellInfo
= spell
->m_spellInfo
;
5225 // check if we can interrupt spell
5226 if ((curSpellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
) && curSpellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
5228 unitTarget
->ProhibitSpellSchool(GetSpellSchoolMask(curSpellInfo
), GetSpellDuration(m_spellInfo
));
5229 unitTarget
->InterruptSpell(CurrentSpellTypes(i
),false);
5235 void Spell::EffectSummonObjectWild(SpellEffectIndex eff_idx
)
5237 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
5239 GameObject
* pGameObj
= new GameObject
;
5241 WorldObject
* target
= focusObject
;
5246 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5248 x
= m_targets
.m_destX
;
5249 y
= m_targets
.m_destY
;
5250 z
= m_targets
.m_destZ
;
5253 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
5255 Map
*map
= target
->GetMap();
5257 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
5258 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
5264 int32 duration
= GetSpellDuration(m_spellInfo
);
5266 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILLISECONDS
: 0);
5267 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5269 // Wild object not have owner and check clickable by players
5272 if(pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5274 Player
*pl
= (Player
*)m_caster
;
5275 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
5277 switch(pGameObj
->GetMapId())
5281 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
5283 uint32 team
= ALLIANCE
;
5285 if(pl
->GetTeam() == team
)
5288 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
5294 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
5296 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
5303 pGameObj
->SummonLinkedTrapIfAny();
5306 void Spell::EffectScriptEffect(SpellEffectIndex eff_idx
)
5308 // TODO: we must implement hunter pet summon at login there (spell 6962)
5310 switch(m_spellInfo
->SpellFamilyName
)
5312 case SPELLFAMILY_GENERIC
:
5314 switch(m_spellInfo
->Id
)
5316 case 8856: // Bending Shinbone
5318 if (!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
5321 uint32 spell_id
= 0;
5324 case 1: spell_id
= 8854; break;
5325 default: spell_id
= 8855; break;
5328 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
5331 case 17512: // Piccolo of the Flaming Fire
5333 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5336 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
5339 case 20589: // Escape artist
5344 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5345 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
5348 case 24590: // Brittle Armor - need remove one 24575 Brittle Armor aura
5349 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
5351 case 26275: // PX-238 Winter Wondervolt TRAP
5353 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
5356 for(int j
= 0; j
< 4; ++j
)
5357 if (unitTarget
->HasAura(spells
[j
], EFFECT_INDEX_0
))
5361 uint32 iTmpSpellId
= spells
[urand(0,3)];
5364 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
5367 case 26465: // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5368 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
5370 case 25140: // Orb teleport spells
5383 switch(m_spellInfo
->Id
)
5385 case 25140: spellid
= 32571; break;
5386 case 25143: spellid
= 32572; break;
5387 case 25650: spellid
= 30140; break;
5388 case 25652: spellid
= 30141; break;
5389 case 29128: spellid
= 32568; break;
5390 case 29129: spellid
= 32569; break;
5391 case 35376: spellid
= 25649; break;
5392 case 35727: spellid
= 35730; break;
5397 unitTarget
->CastSpell(unitTarget
,spellid
,false);
5400 case 22539: // Shadow Flame (All script effects, not just end ones to
5401 case 22972: // prevent player from dodging the last triggered spell)
5414 if (!unitTarget
|| !unitTarget
->isAlive())
5417 // Onyxia Scale Cloak
5418 if (unitTarget
->GetDummyAura(22683))
5422 m_caster
->CastSpell(unitTarget
, 22682, true);
5425 case 26656: // Summon Black Qiraji Battle Tank
5430 // Prevent stacking of mounts
5431 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
5433 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5434 if (unitTarget
->GetAreaId() == 3428)
5435 unitTarget
->CastSpell(unitTarget
, 25863, false);
5437 unitTarget
->CastSpell(unitTarget
, 26655, false);
5441 case 29830: // Mirren's Drinking Hat
5444 switch ( urand(1, 6) )
5449 item
= 23584; break; // Loch Modan Lager
5452 item
= 23585; break; // Stouthammer Lite
5454 item
= 23586; break; // Aerie Peak Pale Ale
5458 DoCreateItem(eff_idx
,item
);
5462 case 30918: // Improved Sprint
5467 // Removes snares and roots.
5468 unitTarget
->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK
,30918,true);
5471 case 41126: // Flame Crash
5476 unitTarget
->CastSpell(unitTarget
, 41131, true);
5479 case 44455: // Character Script Effect Reverse Cast
5481 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
5484 Creature
* pTarget
= (Creature
*)unitTarget
;
5486 if (const SpellEntry
*pSpell
= sSpellStore
.LookupEntry(m_spellInfo
->CalculateSimpleValue(eff_idx
)))
5488 // if we used item at least once...
5489 if (pTarget
->isTemporarySummon() && pTarget
->GetEntry() == pSpell
->EffectMiscValue
[eff_idx
])
5491 TemporarySummon
* pSummon
= (TemporarySummon
*)pTarget
;
5493 // can only affect "own" summoned
5494 if (pSummon
->GetSummonerGuid() == m_caster
->GetObjectGuid())
5496 if (pTarget
->hasUnitState(UNIT_STAT_ROAMING
| UNIT_STAT_ROAMING_MOVE
))
5497 pTarget
->GetMotionMaster()->MovementExpired();
5499 pTarget
->GetMotionMaster()->MovePoint(0, m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ());
5505 // or if we are first time used item
5506 m_caster
->CastSpell(pTarget
, pSpell
, true);
5507 pTarget
->ForcedDespawn();
5512 case 44876: // Force Cast - Portal Effect: Sunwell Isle
5517 unitTarget
->CastSpell(unitTarget
, 44870, true);
5520 case 45668: // Ultra-Advanced Proto-Typical Shortening Blaster
5522 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
5525 if (roll_chance_i(25)) // chance unknown, using 25
5528 static uint32
const spellPlayer
[5] =
5537 static uint32
const spellTarget
[5] =
5546 m_caster
->CastSpell(m_caster
, spellPlayer
[urand(0,4)], true);
5547 unitTarget
->CastSpell(unitTarget
, spellTarget
[urand(0,4)], true);
5551 case 45691: // Magnataur On Death 1
5553 // assuming caster is creature, if not, then return
5554 if (m_caster
->GetTypeId() != TYPEID_UNIT
)
5557 Player
* pPlayer
= ((Creature
*)m_caster
)->GetLootRecipient();
5562 if (pPlayer
->HasAura(45674) || pPlayer
->HasAura(45675) || pPlayer
->HasAura(45678) || pPlayer
->HasAura(45682) || pPlayer
->HasAura(45684))
5563 pPlayer
->CastSpell(pPlayer
, 45686, true);
5565 m_caster
->CastSpell(m_caster
, 45685, true);
5569 case 46203: // Goblin Weather Machine
5577 case 0: spellId
= 46740; break;
5578 case 1: spellId
= 46739; break;
5579 case 2: spellId
= 46738; break;
5580 case 3: spellId
= 46736; break;
5582 unitTarget
->CastSpell(unitTarget
, spellId
, true);
5585 case 46642: //5,000 Gold
5587 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5590 ((Player
*)unitTarget
)->ModifyMoney(50000000);
5593 case 47097: // Surge Needle Teleporter
5595 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5598 if (unitTarget
->GetAreaId() == 4156)
5599 unitTarget
->CastSpell(unitTarget
, 47324, true);
5600 else if (unitTarget
->GetAreaId() == 4157)
5601 unitTarget
->CastSpell(unitTarget
, 47325, true);
5605 case 48603: // High Executor's Branding Iron
5606 // Torture the Torturer: High Executor's Branding Iron Impact
5607 unitTarget
->CastSpell(unitTarget
, 48614, true);
5609 case 51770: // Emblazon Runeblade
5611 Unit
* caster
= GetAffectiveCaster();
5615 caster
->CastSpell(caster
, damage
, false);
5618 case 52751: // Death Gate
5620 if (!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
5623 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5624 unitTarget
->CastSpell(unitTarget
, damage
, false);
5627 case 54729: // Winged Steed of the Ebon Blade
5629 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5632 // Prevent stacking of mounts
5633 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
5635 // Triggered spell id dependent of riding skill
5636 if (uint16 skillval
= ((Player
*)unitTarget
)->GetSkillValue(SKILL_RIDING
))
5638 if (skillval
>= 300)
5639 unitTarget
->CastSpell(unitTarget
, 54727, true);
5641 unitTarget
->CastSpell(unitTarget
, 54726, true);
5645 case 54436: // Demonic Empowerment (succubus Vanish effect)
5650 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5651 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
5652 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
5653 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN
);
5656 case 55693: // Remove Collapsing Cave Aura
5661 unitTarget
->RemoveAurasDueToSpell(m_spellInfo
->CalculateSimpleValue(eff_idx
));
5664 case 58418: // Portal to Orgrimmar
5665 case 58420: // Portal to Stormwind
5667 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| eff_idx
!= EFFECT_INDEX_0
)
5670 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(EFFECT_INDEX_0
);
5671 uint32 questID
= m_spellInfo
->CalculateSimpleValue(EFFECT_INDEX_1
);
5673 if (((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
))
5674 unitTarget
->CastSpell(unitTarget
, spellID
, true);
5678 case 59317: // Teleporting
5680 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5684 if (((Player
*)unitTarget
)->GetAreaId() == 4637)
5685 unitTarget
->CastSpell(unitTarget
, 59316, true);
5688 unitTarget
->CastSpell(unitTarget
, 59314, true);
5691 } // random spell learn instead placeholder
5692 case 60893: // Northrend Alchemy Research
5693 case 61177: // Northrend Inscription Research
5694 case 61288: // Minor Inscription Research
5695 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5696 case 64323: // Book of Glyph Mastery
5698 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
5701 // learn random explicit discovery recipe (if any)
5702 if (uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, (Player
*)m_caster
))
5703 ((Player
*)m_caster
)->learnSpell(discoveredSpell
, false);
5707 case 69377: //Fortitude
5712 m_caster
->CastSpell(unitTarget
, 72590, true);
5715 case 69378: //Blessing of Forgotten Kings
5720 m_caster
->CastSpell(unitTarget
, 72586, true);
5723 case 69381: //Gift of the Wild
5728 m_caster
->CastSpell(unitTarget
, 72588, true);
5734 case SPELLFAMILY_WARLOCK
:
5736 switch(m_spellInfo
->Id
)
5738 case 6201: // Healthstone creating spells
5752 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5753 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
5755 if ((*i
)->GetId() == 18692)
5760 else if ((*i
)->GetId() == 18693)
5767 static uint32
const itypes
[8][3] =
5769 { 5512, 19004, 19005}, // Minor Healthstone
5770 { 5511, 19006, 19007}, // Lesser Healthstone
5771 { 5509, 19008, 19009}, // Healthstone
5772 { 5510, 19010, 19011}, // Greater Healthstone
5773 { 9421, 19012, 19013}, // Major Healthstone
5774 {22103, 22104, 22105}, // Master Healthstone
5775 {36889, 36890, 36891}, // Demonic Healthstone
5776 {36892, 36893, 36894} // Fel Healthstone
5779 switch(m_spellInfo
->Id
)
5782 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
5784 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
5786 itemtype
=itypes
[2][rank
];break; // Healthstone
5788 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
5790 itemtype
=itypes
[4][rank
];break; // Major Healthstone
5792 itemtype
=itypes
[5][rank
];break; // Master Healthstone
5794 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
5796 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
5800 DoCreateItem( eff_idx
, itemtype
);
5803 case 47193: // Demonic Empowerment
5808 uint32 entry
= unitTarget
->GetEntry();
5812 case 416: spellID
= 54444; break; //imp
5813 case 417: spellID
= 54509; break; //fellhunter
5814 case 1860: spellID
= 54443; break; //void
5815 case 1863: spellID
= 54435; break; //succubus
5816 case 17252: spellID
= 54508; break; //fellguard
5820 unitTarget
->CastSpell(unitTarget
,spellID
,true);
5823 case 47422: // Everlasting Affliction
5825 // Need refresh caster corruption auras on target
5826 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
5827 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
5829 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5830 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
5831 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000002)) &&
5832 (*itr
).second
->GetCasterGUID()==m_caster
->GetGUID())
5833 (*itr
).second
->RefreshAura();
5837 case 63521: // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5839 // Divine Plea, refresh on target (3 aura slots)
5840 if (Aura
* aura
= unitTarget
->GetAura(54428, EFFECT_INDEX_0
))
5841 aura
->RefreshAura();
5848 case SPELLFAMILY_PRIEST
:
5850 switch(m_spellInfo
->Id
)
5852 case 47948: // Pain and Suffering
5857 // Refresh Shadow Word: Pain on target
5858 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5859 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5861 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5862 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5863 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000008000)) &&
5864 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5866 (*itr
).second
->RefreshAura();
5877 case SPELLFAMILY_HUNTER
:
5879 switch(m_spellInfo
->Id
)
5881 case 53209: // Chimera Shot
5887 int32 basePoint
= 0;
5888 Unit
* target
= unitTarget
;
5889 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5890 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5892 Aura
*aura
= (*i
).second
;
5893 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5896 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5897 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5898 if (!(familyFlag
& UI64LIT(0x000000800000C000)))
5901 // Refresh aura duration
5902 aura
->RefreshAura();
5904 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5905 if ((familyFlag
& UI64LIT(0x0000000000004000)) && aura
->GetEffIndex() == EFFECT_INDEX_0
)
5907 // m_amount already include RAP bonus
5908 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5909 spellId
= 53353; // Chimera Shot - Serpent
5912 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5913 if ((familyFlag
& UI64LIT(0x0000008000000000)) && aura
->GetEffIndex() == EFFECT_INDEX_0
)
5915 uint32 target_max_mana
= unitTarget
->GetMaxPower(POWER_MANA
);
5916 if (!target_max_mana
)
5919 // ignore non positive values (can be result apply spellmods to aura damage
5920 uint32 pdamage
= aura
->GetModifier()->m_amount
> 0 ? aura
->GetModifier()->m_amount
: 0;
5922 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5923 uint32 maxmana
= m_caster
->GetMaxPower(POWER_MANA
) * pdamage
* 2 / 100;
5925 pdamage
= target_max_mana
* pdamage
/ 100;
5926 if (pdamage
> maxmana
)
5929 pdamage
*= 4; // total aura damage
5930 basePoint
= pdamage
* 60 / 100;
5931 spellId
= 53358; // Chimera Shot - Viper
5935 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5936 if (familyFlag
& UI64LIT(0x0000000000008000))
5937 spellId
= 53359; // Chimera Shot - Scorpid
5938 // ?? nothing say in spell desc (possibly need addition check)
5939 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5940 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5942 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5947 m_caster
->CastCustomSpell(target
, spellId
, &basePoint
, 0, 0, false);
5951 case 53412: // Invigoration (pet triggered script, master targeted)
5956 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5957 for(Unit::AuraList::const_iterator i
= auras
.begin();i
!= auras
.end(); ++i
)
5959 // Invigoration (master talent)
5960 if ((*i
)->GetModifier()->m_miscvalue
== 8 && (*i
)->GetSpellProto()->SpellIconID
== 3487)
5962 if (roll_chance_i((*i
)->GetModifier()->m_amount
))
5964 unitTarget
->CastSpell(unitTarget
, 53398, true, NULL
, (*i
), m_caster
->GetGUID());
5971 case 53271: // Master's Call
5976 // script effect have in value, but this outdated removed part
5977 unitTarget
->CastSpell(unitTarget
, 62305, true);
5985 case SPELLFAMILY_PALADIN
:
5987 // Judgement (seal trigger)
5988 if (m_spellInfo
->Category
== SPELLCATEGORY_JUDGEMENT
)
5990 if (!unitTarget
|| !unitTarget
->isAlive())
5993 uint32 spellId1
= 0;
5994 uint32 spellId2
= 0;
5996 // Judgement self add switch
5997 switch (m_spellInfo
->Id
)
5999 case 53407: spellId1
= 20184; break; // Judgement of Justice
6000 case 20271: // Judgement of Light
6001 case 57774: spellId1
= 20185; break; // Judgement of Light
6002 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
6004 sLog
.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo
->Id
);
6008 // offensive seals have aura dummy in 2 effect
6009 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
6010 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
6012 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
6013 if ((*itr
)->GetEffIndex() != EFFECT_INDEX_2
|| !IsSealSpell((*itr
)->GetSpellProto()))
6015 spellId2
= (*itr
)->GetModifier()->m_amount
;
6016 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
6022 // if there were no offensive seals than there is seal with proc trigger aura
6025 Unit::AuraList
const& procTriggerAuras
= m_caster
->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL
);
6026 for(Unit::AuraList::const_iterator itr
= procTriggerAuras
.begin(); itr
!= procTriggerAuras
.end(); ++itr
)
6028 if ((*itr
)->GetEffIndex() != EFFECT_INDEX_0
|| !IsSealSpell((*itr
)->GetSpellProto()))
6036 m_caster
->CastSpell(unitTarget
, spellId1
, true);
6039 m_caster
->CastSpell(unitTarget
, spellId2
, true);
6044 case SPELLFAMILY_POTION
:
6046 switch(m_spellInfo
->Id
)
6048 case 28698: // Dreaming Glory
6053 unitTarget
->CastSpell(unitTarget
, 28694, true);
6056 case 28702: // Netherbloom
6061 // 25% chance of casting a random buff
6062 if (roll_chance_i(75))
6065 // triggered spells are 28703 to 28707
6066 // Note: some sources say, that there was the possibility of
6067 // receiving a debuff. However, this seems to be removed by a patch.
6068 const uint32 spellid
= 28703;
6070 // don't overwrite an existing aura
6071 for(uint8 i
= 0; i
< 5; ++i
)
6072 if (unitTarget
->HasAura(spellid
+ i
, EFFECT_INDEX_0
))
6075 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
6078 case 28720: // Nightmare Vine
6083 // 25% chance of casting Nightmare Pollen
6084 if (roll_chance_i(75))
6087 unitTarget
->CastSpell(unitTarget
, 28721, true);
6093 case SPELLFAMILY_DEATHKNIGHT
:
6095 switch(m_spellInfo
->Id
)
6097 case 50842: // Pestilence
6102 Unit
* mainTarget
= m_targets
.getUnitTarget();
6106 // do only refresh diseases on main target if caster has Glyph of Disease
6107 if (mainTarget
== unitTarget
&& !m_caster
->HasAura(63334))
6111 if (mainTarget
->HasAura(55078))
6112 m_caster
->CastSpell(unitTarget
, 55078, true);
6115 if (mainTarget
->HasAura(55095))
6116 m_caster
->CastSpell(unitTarget
, 55095, true);
6125 // normal DB scripted effect
6129 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
6130 m_caster
->GetMap()->ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
6133 void Spell::EffectSanctuary(SpellEffectIndex
/*eff_idx*/)
6137 //unitTarget->CombatStop();
6139 unitTarget
->CombatStop();
6140 unitTarget
->getHostileRefManager().deleteReferences(); // stop all fighting
6141 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
6142 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
6144 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
6148 void Spell::EffectAddComboPoints(SpellEffectIndex
/*eff_idx*/)
6153 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6159 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
6162 void Spell::EffectDuel(SpellEffectIndex eff_idx
)
6164 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6167 Player
*caster
= (Player
*)m_caster
;
6168 Player
*target
= (Player
*)unitTarget
;
6170 // caster or target already have requested duel
6171 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
6174 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
6175 // Don't have to check the target's map since you cannot challenge someone across maps
6176 uint32 mapid
= caster
->GetMapId();
6177 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
6179 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
6183 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
6184 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
6186 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
6190 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
6191 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
6193 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
6197 //CREATE DUEL FLAG OBJECT
6198 GameObject
* pGameObj
= new GameObject
;
6200 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6202 Map
*map
= m_caster
->GetMap();
6203 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
6204 map
, m_caster
->GetPhaseMask(),
6205 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
6206 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
6207 m_caster
->GetPositionZ(),
6208 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
6214 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
6215 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
6216 int32 duration
= GetSpellDuration(m_spellInfo
);
6217 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILLISECONDS
: 0);
6218 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6220 m_caster
->AddGameObject(pGameObj
);
6225 WorldPacket
data(SMSG_DUEL_REQUESTED
, 8 + 8);
6226 data
<< uint64(pGameObj
->GetGUID());
6227 data
<< uint64(caster
->GetGUID());
6228 caster
->GetSession()->SendPacket(&data
);
6229 target
->GetSession()->SendPacket(&data
);
6232 DuelInfo
*duel
= new DuelInfo
;
6233 duel
->initiator
= caster
;
6234 duel
->opponent
= target
;
6235 duel
->startTime
= 0;
6236 duel
->startTimer
= 0;
6237 caster
->duel
= duel
;
6239 DuelInfo
*duel2
= new DuelInfo
;
6240 duel2
->initiator
= caster
;
6241 duel2
->opponent
= caster
;
6242 duel2
->startTime
= 0;
6243 duel2
->startTimer
= 0;
6244 target
->duel
= duel2
;
6246 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
6247 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
6250 void Spell::EffectStuck(SpellEffectIndex
/*eff_idx*/)
6252 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6255 if(!sWorld
.getConfig(CONFIG_BOOL_CAST_UNSTUCK
))
6258 Player
* pTarget
= (Player
*)unitTarget
;
6260 sLog
.outDebug("Spell Effect: Stuck");
6261 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());
6263 if(pTarget
->isInFlight())
6266 // homebind location is loaded always
6267 pTarget
->TeleportToHomebind(unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
6269 // Stuck spell trigger Hearthstone cooldown
6270 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
6273 Spell
spell(pTarget
, spellInfo
, true, 0);
6274 spell
.SendSpellCooldown();
6277 void Spell::EffectSummonPlayer(SpellEffectIndex
/*eff_idx*/)
6279 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6282 // Evil Twin (ignore player summon, but hide this for summoner)
6283 if(unitTarget
->GetDummyAura(23445))
6287 m_caster
->GetClosePoint(x
, y
, z
, unitTarget
->GetObjectSize());
6289 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
6291 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
6292 data
<< uint64(m_caster
->GetGUID()); // summoner guid
6293 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
6294 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILLISECONDS
); // auto decline after msecs
6295 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6298 static ScriptInfo
generateActivateCommand()
6301 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
6305 void Spell::EffectActivateObject(SpellEffectIndex eff_idx
)
6310 static ScriptInfo activateCommand
= generateActivateCommand();
6312 int32 delay_secs
= m_spellInfo
->CalculateSimpleValue(eff_idx
);
6314 gameObjTarget
->GetMap()->ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
6317 void Spell::EffectApplyGlyph(SpellEffectIndex eff_idx
)
6319 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6322 Player
*player
= (Player
*)m_caster
;
6325 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[eff_idx
])
6327 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
6329 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
6331 if(gp
->TypeFlags
!= gs
->TypeFlags
)
6333 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
6334 return; // glyph slot mismatch
6339 player
->ApplyGlyph(m_glyphIndex
, false);
6340 player
->SetGlyph(m_glyphIndex
, glyph
);
6341 player
->ApplyGlyph(m_glyphIndex
, true);
6342 player
->SendTalentsInfoData(false);
6347 void Spell::DoSummonTotem(SpellEffectIndex eff_idx
, uint8 slot_dbc
)
6349 // DBC store slots starting from 1, with no slot 0 value)
6350 int slot
= slot_dbc
? slot_dbc
- 1 : TOTEM_SLOT_NONE
;
6352 // unsummon old totem
6353 if(slot
< MAX_TOTEM_SLOT
)
6354 if (Totem
*OldTotem
= m_caster
->GetTotem(TotemSlot(slot
)))
6355 OldTotem
->UnSummon();
6358 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
6359 team
= ((Player
*)m_caster
)->GetTeam();
6361 Totem
* pTotem
= new Totem
;
6363 if(!pTotem
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
6364 m_spellInfo
->EffectMiscValue
[eff_idx
], team
))
6370 float angle
= slot
< MAX_TOTEM_SLOT
? M_PI_F
/MAX_TOTEM_SLOT
- (slot
*2*M_PI_F
/MAX_TOTEM_SLOT
) : 0;
6373 m_caster
->GetClosePoint(x
, y
, z
, pTotem
->GetObjectSize(), 2.0f
, angle
);
6375 // totem must be at same Z in case swimming caster and etc.
6376 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
6377 z
= m_caster
->GetPositionZ();
6379 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
6380 pTotem
->SetSummonPoint(x
, y
, z
, m_caster
->GetOrientation());
6382 if (slot
< MAX_TOTEM_SLOT
)
6383 m_caster
->_AddTotem(TotemSlot(slot
),pTotem
);
6385 pTotem
->SetOwner(m_caster
->GetGUID());
6386 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initialized
6388 int32 duration
=GetSpellDuration(m_spellInfo
);
6389 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
6390 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
6391 pTotem
->SetDuration(duration
);
6393 if (damage
) // if not spell info, DB values used
6395 pTotem
->SetMaxHealth(damage
);
6396 pTotem
->SetHealth(damage
);
6399 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
6401 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
6402 pTotem
->SetFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_PVP_ATTACKABLE
);
6404 if(m_caster
->IsPvP())
6405 pTotem
->SetPvP(true);
6407 if(m_caster
->IsFFAPvP())
6408 pTotem
->SetFFAPvP(true);
6410 pTotem
->Summon(m_caster
);
6412 if (slot
< MAX_TOTEM_SLOT
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
6414 WorldPacket
data(SMSG_TOTEM_CREATED
, 1 + 8 + 4 + 4);
6415 data
<< uint8(slot
);
6416 data
<< uint64(pTotem
->GetGUID());
6417 data
<< uint32(duration
);
6418 data
<< uint32(m_spellInfo
->Id
);
6419 ((Player
*)m_caster
)->SendDirectMessage(&data
);
6423 void Spell::EffectEnchantHeldItem(SpellEffectIndex eff_idx
)
6425 // this is only item spell effect applied to main-hand weapon of target player (players in area)
6426 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6429 Player
* item_owner
= (Player
*)unitTarget
;
6430 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
6436 if(!item
->IsEquipped())
6439 if (m_spellInfo
->EffectMiscValue
[eff_idx
])
6441 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6442 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
6444 duration
= m_currentBasePoints
[eff_idx
]+1; //Base points after ..
6446 duration
= 10; //10 seconds for enchants which don't have listed duration
6448 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
6452 // Always go to temp enchantment slot
6453 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
6455 // Enchantment will not be applied if a different one already exists
6456 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
6459 // Apply the temporary enchantment
6460 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILLISECONDS
, 0);
6461 item_owner
->ApplyEnchantment(item
, slot
, true);
6465 void Spell::EffectDisEnchant(SpellEffectIndex
/*eff_idx*/)
6467 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6470 Player
* p_caster
= (Player
*)m_caster
;
6471 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
6474 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
6476 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
6478 // item will be removed at disenchanting end
6481 void Spell::EffectInebriate(SpellEffectIndex
/*eff_idx*/)
6483 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6486 Player
*player
= (Player
*)unitTarget
;
6487 uint16 currentDrunk
= player
->GetDrunkValue();
6488 uint16 drunkMod
= damage
* 256;
6489 if (currentDrunk
+ drunkMod
> 0xFFFF)
6490 currentDrunk
= 0xFFFF;
6492 currentDrunk
+= drunkMod
;
6493 player
->SetDrunkValue(currentDrunk
, m_CastItem
? m_CastItem
->GetEntry() : 0);
6496 void Spell::EffectFeedPet(SpellEffectIndex eff_idx
)
6498 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6501 Player
*_player
= (Player
*)m_caster
;
6503 Item
* foodItem
= m_targets
.getItemTarget();
6507 Pet
*pet
= _player
->GetPet();
6514 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
6519 _player
->DestroyItemCount(foodItem
,count
,true);
6520 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6522 m_caster
->CastCustomSpell(pet
, m_spellInfo
->EffectTriggerSpell
[eff_idx
], &benefit
, NULL
, NULL
, true);
6525 void Spell::EffectDismissPet(SpellEffectIndex
/*eff_idx*/)
6527 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6530 Pet
* pet
= m_caster
->GetPet();
6532 // not let dismiss dead pet
6533 if(!pet
||!pet
->isAlive())
6536 ((Player
*)m_caster
)->RemovePet(pet
, PET_SAVE_NOT_IN_SLOT
);
6539 void Spell::EffectSummonObject(SpellEffectIndex eff_idx
)
6541 uint32 go_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6544 switch(m_spellInfo
->Effect
[eff_idx
])
6546 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
6547 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
6548 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
6549 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
6553 if(uint64 guid
= m_caster
->m_ObjectSlot
[slot
])
6555 if(GameObject
* obj
= m_caster
? m_caster
->GetMap()->GetGameObject(guid
) : NULL
)
6556 obj
->SetLootState(GO_JUST_DEACTIVATED
);
6557 m_caster
->m_ObjectSlot
[slot
] = 0;
6560 GameObject
* pGameObj
= new GameObject
;
6563 // If dest location if present
6564 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6566 x
= m_targets
.m_destX
;
6567 y
= m_targets
.m_destY
;
6568 z
= m_targets
.m_destZ
;
6570 // Summon in random point all other units if location present
6572 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
6574 Map
*map
= m_caster
->GetMap();
6575 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
6576 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
6582 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
6583 int32 duration
= GetSpellDuration(m_spellInfo
);
6584 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILLISECONDS
: 0);
6585 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6586 m_caster
->AddGameObject(pGameObj
);
6590 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
6592 pGameObj
->SummonLinkedTrapIfAny();
6595 void Spell::EffectResurrect(SpellEffectIndex
/*eff_idx*/)
6599 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6602 if(unitTarget
->isAlive())
6604 if(!unitTarget
->IsInWorld())
6607 switch (m_spellInfo
->Id
)
6609 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6611 if (roll_chance_i(67))
6613 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
6617 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6619 if (roll_chance_i(50))
6621 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
6629 Player
* pTarget
= ((Player
*)unitTarget
);
6631 if(pTarget
->isRessurectRequested()) // already have one active request
6634 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
6635 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
6637 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
6638 SendResurrectRequest(pTarget
);
6641 void Spell::EffectAddExtraAttacks(SpellEffectIndex
/*eff_idx*/)
6643 if(!unitTarget
|| !unitTarget
->isAlive())
6646 if( unitTarget
->m_extraAttacks
)
6649 unitTarget
->m_extraAttacks
= damage
;
6652 void Spell::EffectParry(SpellEffectIndex
/*eff_idx*/)
6654 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6655 ((Player
*)unitTarget
)->SetCanParry(true);
6658 void Spell::EffectBlock(SpellEffectIndex
/*eff_idx*/)
6660 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6661 ((Player
*)unitTarget
)->SetCanBlock(true);
6664 void Spell::EffectLeapForward(SpellEffectIndex eff_idx
)
6666 if(unitTarget
->isInFlight())
6669 if( m_spellInfo
->rangeIndex
== 1) //self range
6671 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
6675 unitTarget
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
6677 unitTarget
->GetPosition(ox
, oy
, oz
);
6679 float fx2
, fy2
, fz2
; // getObjectHitPos overwrite last args in any result case
6680 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5f
, fx
,fy
,oz
+0.5f
,fx2
,fy2
,fz2
, -0.5f
))
6685 unitTarget
->UpdateGroundPositionZ(fx
, fy
, fz
);
6688 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(), unitTarget
== m_caster
);
6692 void Spell::EffectLeapBack(SpellEffectIndex eff_idx
)
6694 if(unitTarget
->isInFlight())
6697 m_caster
->KnockBackFrom(unitTarget
,float(m_spellInfo
->EffectMiscValue
[eff_idx
])/10,float(damage
)/10);
6700 void Spell::EffectReputation(SpellEffectIndex eff_idx
)
6702 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6705 Player
*_player
= (Player
*)unitTarget
;
6707 int32 rep_change
= m_currentBasePoints
[eff_idx
]+1; // field store reputation change -1
6709 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6711 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
6716 _player
->GetReputationMgr().ModifyReputation(factionEntry
, rep_change
);
6719 void Spell::EffectQuestComplete(SpellEffectIndex eff_idx
)
6721 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6724 Player
*_player
= (Player
*)m_caster
;
6726 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6727 _player
->AreaExploredOrEventHappens(quest_id
);
6730 void Spell::EffectSelfResurrect(SpellEffectIndex eff_idx
)
6732 if(!unitTarget
|| unitTarget
->isAlive())
6734 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6736 if(!unitTarget
->IsInWorld())
6745 health
= uint32(-damage
);
6746 mana
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6751 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
6752 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
6753 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
6756 Player
*plr
= ((Player
*)unitTarget
);
6757 plr
->ResurrectPlayer(0.0f
);
6759 plr
->SetHealth( health
);
6760 plr
->SetPower(POWER_MANA
, mana
);
6761 plr
->SetPower(POWER_RAGE
, 0 );
6762 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
6764 plr
->SpawnCorpseBones();
6767 void Spell::EffectSkinning(SpellEffectIndex
/*eff_idx*/)
6769 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
6771 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
6774 Creature
* creature
= (Creature
*) unitTarget
;
6775 int32 targetLevel
= creature
->getLevel();
6777 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
6779 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
6780 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6782 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
6784 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
6786 // Double chances for elites
6787 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
6790 void Spell::EffectCharge(SpellEffectIndex
/*eff_idx*/)
6795 //TODO: research more ContactPoint/attack distance.
6796 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6798 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6800 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6801 ((Creature
*)unitTarget
)->StopMoving();
6803 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6804 m_caster
->MonsterMove(x
, y
, z
, 1);
6806 // not all charge effects used in negative spells
6807 if (unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6808 m_caster
->Attack(unitTarget
, true);
6811 void Spell::EffectCharge2(SpellEffectIndex
/*eff_idx*/)
6814 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6816 x
= m_targets
.m_destX
;
6817 y
= m_targets
.m_destY
;
6818 z
= m_targets
.m_destZ
;
6820 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6821 ((Creature
*)unitTarget
)->StopMoving();
6823 else if (unitTarget
&& unitTarget
!= m_caster
)
6824 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6828 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6829 m_caster
->MonsterMove(x
, y
, z
, 1);
6831 // not all charge effects used in negative spells
6832 if (unitTarget
&& unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6833 m_caster
->Attack(unitTarget
, true);
6836 void Spell::DoSummonCritter(SpellEffectIndex eff_idx
, uint32 forceFaction
)
6838 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6840 Player
* player
= (Player
*)m_caster
;
6842 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6846 Pet
* old_critter
= player
->GetMiniPet();
6848 // for same pet just despawn
6849 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
6851 player
->RemoveMiniPet();
6855 // despawn old pet before summon new
6857 player
->RemoveMiniPet();
6860 Pet
* critter
= new Pet(MINI_PET
);
6862 Map
*map
= m_caster
->GetMap();
6863 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
6864 if(!critter
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
6865 pet_entry
, pet_number
))
6867 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
6873 // If dest location if present
6874 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6876 x
= m_targets
.m_destX
;
6877 y
= m_targets
.m_destY
;
6878 z
= m_targets
.m_destZ
;
6880 // Summon if dest location not present near caster
6882 m_caster
->GetClosePoint(x
, y
, z
, critter
->GetObjectSize());
6884 critter
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
6885 critter
->SetSummonPoint(x
, y
, z
, m_caster
->GetOrientation());
6887 if(!critter
->IsPositionValid())
6889 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6890 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
6895 critter
->SetOwnerGUID(m_caster
->GetGUID());
6896 critter
->SetCreatorGUID(m_caster
->GetGUID());
6898 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
6899 critter
->setFaction(forceFaction
? forceFaction
: m_caster
->getFaction());
6900 critter
->AIM_Initialize();
6901 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6902 //critter->InitLevelupSpellsForLevel(); // none?
6903 critter
->SelectLevel(critter
->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6904 critter
->SetUInt32Value(UNIT_NPC_FLAGS
, critter
->GetCreatureInfo()->npcflag
);
6905 // some mini-pets have quests
6907 // set timer for unsummon
6908 int32 duration
= GetSpellDuration(m_spellInfo
);
6910 critter
->SetDuration(duration
);
6912 std::string name
= player
->GetName();
6913 name
.append(petTypeSuffix
[critter
->getPetType()]);
6914 critter
->SetName( name
);
6915 player
->SetMiniPet(critter
);
6917 map
->Add((Creature
*)critter
);
6920 void Spell::EffectKnockBack(SpellEffectIndex eff_idx
)
6925 unitTarget
->KnockBackFrom(m_caster
,float(m_spellInfo
->EffectMiscValue
[eff_idx
])/10,float(damage
)/10);
6928 void Spell::EffectSendTaxi(SpellEffectIndex eff_idx
)
6930 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6933 ((Player
*)unitTarget
)->ActivateTaxiPathTo(m_spellInfo
->EffectMiscValue
[eff_idx
],m_spellInfo
->Id
);
6936 void Spell::EffectPlayerPull(SpellEffectIndex eff_idx
)
6941 float dist
= unitTarget
->GetDistance2d(m_caster
);
6942 if (damage
&& dist
> damage
)
6943 dist
= float(damage
);
6945 unitTarget
->KnockBackFrom(m_caster
,-dist
,float(m_spellInfo
->EffectMiscValue
[eff_idx
])/10);
6948 void Spell::EffectDispelMechanic(SpellEffectIndex eff_idx
)
6953 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[eff_idx
];
6955 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6956 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6960 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6961 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6963 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6967 next
= Auras
.begin();
6973 void Spell::EffectSummonDeadPet(SpellEffectIndex
/*eff_idx*/)
6975 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6977 Player
*_player
= (Player
*)m_caster
;
6978 Pet
*pet
= _player
->GetPet();
6985 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6986 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6987 pet
->setDeathState( ALIVE
);
6988 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6989 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6991 pet
->AIM_Initialize();
6993 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6994 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6997 void Spell::EffectSummonAllTotems(SpellEffectIndex eff_idx
)
6999 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
7002 int32 start_button
= ACTION_BUTTON_SHAMAN_TOTEMS_BAR
+ m_spellInfo
->EffectMiscValue
[eff_idx
];
7003 int32 amount_buttons
= m_spellInfo
->EffectMiscValueB
[eff_idx
];
7005 for(int32 slot
= 0; slot
< amount_buttons
; ++slot
)
7006 if (ActionButton
const* actionButton
= ((Player
*)m_caster
)->GetActionButton(start_button
+slot
))
7007 if (actionButton
->GetType()==ACTION_BUTTON_SPELL
)
7008 if (uint32 spell_id
= actionButton
->GetAction())
7009 m_caster
->CastSpell(unitTarget
,spell_id
,true);
7012 void Spell::EffectDestroyAllTotems(SpellEffectIndex
/*eff_idx*/)
7015 for(int slot
= 0; slot
< MAX_TOTEM_SLOT
; ++slot
)
7017 if (Totem
* totem
= m_caster
->GetTotem(TotemSlot(slot
)))
7019 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
7020 if (SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
))
7022 uint32 manacost
= m_caster
->GetCreateMana() * spellInfo
->ManaCostPercentage
/ 100;
7023 mana
+= manacost
* damage
/ 100;
7030 m_caster
->CastCustomSpell(m_caster
, 39104, &mana
, NULL
, NULL
, true);
7033 void Spell::EffectDurabilityDamage(SpellEffectIndex eff_idx
)
7035 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7038 int32 slot
= m_spellInfo
->EffectMiscValue
[eff_idx
];
7040 // FIXME: some spells effects have value -1/-2
7041 // Possibly its mean -1 all player equipped items and -2 all items
7044 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
, (slot
< -1));
7048 // invalid slot value
7049 if(slot
>= INVENTORY_SLOT_BAG_END
)
7052 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
7053 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
, damage
);
7056 void Spell::EffectDurabilityDamagePCT(SpellEffectIndex eff_idx
)
7058 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7061 int32 slot
= m_spellInfo
->EffectMiscValue
[eff_idx
];
7063 // FIXME: some spells effects have value -1/-2
7064 // Possibly its mean -1 all player equipped items and -2 all items
7067 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
, (slot
< -1));
7071 // invalid slot value
7072 if(slot
>= INVENTORY_SLOT_BAG_END
)
7078 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
7079 ((Player
*)unitTarget
)->DurabilityLoss(item
, double(damage
)/100.0f
);
7082 void Spell::EffectModifyThreatPercent(SpellEffectIndex
/*eff_idx*/)
7087 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
7090 void Spell::EffectTransmitted(SpellEffectIndex eff_idx
)
7092 uint32 name_id
= m_spellInfo
->EffectMiscValue
[eff_idx
];
7094 GameObjectInfo
const* goinfo
= ObjectMgr::GetGameObjectInfo(name_id
);
7098 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
7104 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
7106 fx
= m_targets
.m_destX
;
7107 fy
= m_targets
.m_destY
;
7108 fz
= m_targets
.m_destZ
;
7110 //FIXME: this can be better check for most objects but still hack
7111 else if(m_spellInfo
->EffectRadiusIndex
[eff_idx
] && m_spellInfo
->speed
==0)
7113 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[eff_idx
]));
7114 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
7118 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
7119 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
7120 float dis
= rand_norm_f() * (max_dis
- min_dis
) + min_dis
;
7122 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
7125 Map
*cMap
= m_caster
->GetMap();
7127 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
7129 if ( !cMap
->IsInWater(fx
, fy
, fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
7130 { // but this is not proper, we really need to ignore not materialized objects
7131 SendCastResult(SPELL_FAILED_NOT_HERE
);
7132 SendChannelUpdate(0);
7136 // replace by water level in this case
7137 fz
= cMap
->GetWaterLevel(fx
, fy
);
7139 // if gameobject is summoning object, it should be spawned right on caster's position
7140 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
7142 m_caster
->GetPosition(fx
, fy
, fz
);
7145 GameObject
* pGameObj
= new GameObject
;
7147 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
7148 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
7154 int32 duration
= GetSpellDuration(m_spellInfo
);
7156 switch(goinfo
->type
)
7158 case GAMEOBJECT_TYPE_FISHINGNODE
:
7160 m_caster
->SetChannelObjectGUID(pGameObj
->GetGUID());
7161 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
7163 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
7164 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
7168 case 0: lastSec
= 3; break;
7169 case 1: lastSec
= 7; break;
7170 case 2: lastSec
= 13; break;
7171 case 3: lastSec
= 17; break;
7174 duration
= duration
- lastSec
*IN_MILLISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILLISECONDS
;
7177 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
7179 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
7181 pGameObj
->AddUniqueUse((Player
*)m_caster
);
7182 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
7186 case GAMEOBJECT_TYPE_FISHINGHOLE
:
7187 case GAMEOBJECT_TYPE_CHEST
:
7192 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILLISECONDS
: 0);
7194 pGameObj
->SetOwnerGUID(m_caster
->GetGUID());
7196 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel());
7197 pGameObj
->SetSpellId(m_spellInfo
->Id
);
7199 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
7200 //m_caster->AddGameObject(pGameObj);
7201 //m_ObjToDel.push_back(pGameObj);
7203 cMap
->Add(pGameObj
);
7205 pGameObj
->SummonLinkedTrapIfAny();
7208 void Spell::EffectProspecting(SpellEffectIndex
/*eff_idx*/)
7210 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
7213 Player
* p_caster
= (Player
*)m_caster
;
7214 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
7217 if(itemTarget
->GetCount() < 5)
7220 if( sWorld
.getConfig(CONFIG_BOOL_SKILL_PROSPECTING
))
7222 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
7223 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
7224 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
7227 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
7230 void Spell::EffectMilling(SpellEffectIndex
/*eff_idx*/)
7232 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
7235 Player
* p_caster
= (Player
*)m_caster
;
7236 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
7239 if(itemTarget
->GetCount() < 5)
7242 if( sWorld
.getConfig(CONFIG_BOOL_SKILL_MILLING
))
7244 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
7245 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
7246 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
7249 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
7252 void Spell::EffectSkill(SpellEffectIndex
/*eff_idx*/)
7254 sLog
.outDebug("WORLD: SkillEFFECT");
7257 void Spell::EffectSpiritHeal(SpellEffectIndex
/*eff_idx*/)
7259 // TODO player can't see the heal-animation - he should respawn some ticks later
7260 if (!unitTarget
|| unitTarget
->isAlive())
7262 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7264 if (!unitTarget
->IsInWorld())
7266 if (m_spellInfo
->Id
== 22012 && !unitTarget
->HasAura(2584))
7269 ((Player
*)unitTarget
)->ResurrectPlayer(1.0f
);
7270 ((Player
*)unitTarget
)->SpawnCorpseBones();
7273 // remove insignia spell effect
7274 void Spell::EffectSkinPlayerCorpse(SpellEffectIndex
/*eff_idx*/)
7276 sLog
.outDebug("Effect: SkinPlayerCorpse");
7277 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
7280 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
7283 void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx
)
7285 sLog
.outDebug("Effect: StealBeneficialBuff");
7287 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
7290 std::vector
<Aura
*> steal_list
;
7291 // Create dispel mask by dispel type
7292 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[eff_idx
]) );
7293 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
7294 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
7296 Aura
*aur
= (*itr
).second
;
7297 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
7299 // Need check for passive? this
7300 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
7301 steal_list
.push_back(aur
);
7304 // Ok if exist some buffs for dispel try dispel it
7305 if (!steal_list
.empty())
7307 std::list
< std::pair
<uint32
,uint64
> > success_list
;
7308 int32 list_size
= steal_list
.size();
7309 // Dispell N = damage buffs (or while exist buffs for dispel)
7310 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
7312 // Random select buff for dispel
7313 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
7314 // Not use chance for steal
7315 // TODO possible need do it
7316 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
7318 // Remove buff from list for prevent doubles
7319 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
7322 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
7324 j
= steal_list
.erase(j
);
7331 // Really try steal and send log
7332 if (!success_list
.empty())
7334 int32 count
= success_list
.size();
7335 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
7336 data
<< unitTarget
->GetPackGUID(); // Victim GUID
7337 data
<< m_caster
->GetPackGUID(); // Caster GUID
7338 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
7339 data
<< uint8(0); // not used
7340 data
<< uint32(count
); // count
7341 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
7343 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
7344 data
<< uint32(spellInfo
->Id
); // Spell Id
7345 data
<< uint8(0); // 0 - steals !=0 transfers
7346 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
7348 m_caster
->SendMessageToSet(&data
, true);
7353 void Spell::EffectKillCreditPersonal(SpellEffectIndex eff_idx
)
7355 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7358 ((Player
*)unitTarget
)->KilledMonsterCredit(m_spellInfo
->EffectMiscValue
[eff_idx
], 0);
7361 void Spell::EffectKillCredit(SpellEffectIndex eff_idx
)
7363 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7366 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[eff_idx
], unitTarget
);
7369 void Spell::EffectQuestFail(SpellEffectIndex eff_idx
)
7371 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7374 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[eff_idx
]);
7377 void Spell::EffectActivateRune(SpellEffectIndex eff_idx
)
7379 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
7382 Player
*plr
= (Player
*)m_caster
;
7384 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
7387 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
7389 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == RuneType(m_spellInfo
->EffectMiscValue
[eff_idx
]))
7391 plr
->SetRuneCooldown(j
, 0);
7396 void Spell::EffectTitanGrip(SpellEffectIndex
/*eff_idx*/)
7398 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
7399 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
7402 void Spell::EffectRenamePet(SpellEffectIndex
/*eff_idx*/)
7404 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
7405 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
7408 unitTarget
->RemoveByteFlag(UNIT_FIELD_BYTES_2
, 2, UNIT_CAN_BE_RENAMED
);
7411 void Spell::EffectPlayMusic(SpellEffectIndex eff_idx
)
7413 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7416 uint32 soundid
= m_spellInfo
->EffectMiscValue
[eff_idx
];
7418 if (!sSoundEntriesStore
.LookupEntry(soundid
))
7420 sLog
.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid
,m_spellInfo
->Id
);
7424 WorldPacket
data(SMSG_PLAY_MUSIC
, 4);
7425 data
<< uint32(soundid
);
7426 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
7429 void Spell::EffectSpecCount(SpellEffectIndex
/*eff_idx*/)
7431 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7434 ((Player
*)unitTarget
)->UpdateSpecCount(damage
);
7437 void Spell::EffectActivateSpec(SpellEffectIndex
/*eff_idx*/)
7439 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7442 uint32 spec
= damage
-1;
7444 ((Player
*)unitTarget
)->ActivateSpec(spec
);
7447 void Spell::EffectBind(SpellEffectIndex eff_idx
)
7449 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7452 Player
* player
= (Player
*)unitTarget
;
7456 if (m_spellInfo
->EffectImplicitTargetA
[eff_idx
] == TARGET_TABLE_X_Y_Z_COORDINATES
||
7457 m_spellInfo
->EffectImplicitTargetB
[eff_idx
] == TARGET_TABLE_X_Y_Z_COORDINATES
)
7459 SpellTargetPosition
const* st
= sSpellMgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
7462 sLog
.outError( "Spell::EffectBind - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
7466 loc
.mapid
= st
->target_mapId
;
7467 loc
.coord_x
= st
->target_X
;
7468 loc
.coord_y
= st
->target_Y
;
7469 loc
.coord_z
= st
->target_Y
;
7470 loc
.orientation
= st
->target_Orientation
;
7471 area_id
= sMapMgr
.GetAreaId(loc
.mapid
, loc
.coord_x
, loc
.coord_y
, loc
.coord_z
);
7475 player
->GetPosition(loc
);
7476 area_id
= player
->GetAreaId();
7479 player
->SetHomebindToLocation(loc
,area_id
);
7482 WorldPacket
data( SMSG_BINDPOINTUPDATE
, (4+4+4+4+4) );
7483 data
<< float(loc
.coord_x
);
7484 data
<< float(loc
.coord_y
);
7485 data
<< float(loc
.coord_z
);
7486 data
<< uint32(loc
.mapid
);
7487 data
<< uint32(area_id
);
7488 player
->SendDirectMessage( &data
);
7490 DEBUG_LOG("New Home Position X is %f", loc
.coord_x
);
7491 DEBUG_LOG("New Home Position Y is %f", loc
.coord_y
);
7492 DEBUG_LOG("New Home Position Z is %f", loc
.coord_z
);
7493 DEBUG_LOG("New Home MapId is %u", loc
.mapid
);
7494 DEBUG_LOG("New Home AreaId is %u", area_id
);
7497 data
.Initialize(SMSG_PLAYERBOUND
, 8+4);
7498 data
<< uint64(player
->GetGUID());
7499 data
<< uint32(area_id
);
7500 player
->SendDirectMessage( &data
);
7503 void Spell::EffectRestoreItemCharges( SpellEffectIndex eff_idx
)
7505 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7508 Player
* player
= (Player
*)unitTarget
;
7510 ItemPrototype
const* itemProto
= ObjectMgr::GetItemPrototype(m_spellInfo
->EffectItemType
[eff_idx
]);
7514 // In case item from limited category recharge any from category, is this valid checked early in spell checks
7516 if (itemProto
->ItemLimitCategory
)
7517 item
= player
->GetItemByLimitedCategory(itemProto
->ItemLimitCategory
);
7519 item
= player
->GetItemByEntry(m_spellInfo
->EffectItemType
[eff_idx
]);
7524 item
->RestoreCharges();
7527 void Spell::EffectTeachTaxiNode( SpellEffectIndex eff_idx
)
7529 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
7532 Player
* player
= (Player
*)unitTarget
;
7534 uint32 taxiNodeId
= m_spellInfo
->EffectMiscValue
[eff_idx
];
7535 if (!sTaxiNodesStore
.LookupEntry(taxiNodeId
))
7538 if (player
->m_taxi
.SetTaximaskNode(taxiNodeId
))
7540 WorldPacket
data(SMSG_NEW_TAXI_PATH
, 0);
7541 player
->SendDirectMessage( &data
);
7543 data
.Initialize( SMSG_TAXINODE_STATUS
, 9 );
7544 data
<< uint64( m_caster
->GetGUID() );
7546 player
->SendDirectMessage( &data
);