2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
26 #include "UpdateMask.h"
28 #include "ObjectMgr.h"
31 #include "SkillExtraItems.h"
33 #include "CreatureAI.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
47 #include "CreatureAI.h"
48 #include "BattleGround.h"
49 #include "BattleGroundEY.h"
50 #include "BattleGroundWS.h"
51 #include "VMapFactory.h"
53 #include "SocialMgr.h"
55 #include "TemporarySummon.h"
57 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
59 &Spell::EffectNULL
, // 0
60 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
61 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
62 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
63 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
64 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
65 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
66 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
67 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
68 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
69 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
70 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
71 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
72 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
73 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
74 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
75 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
76 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
77 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
78 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
79 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
80 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
81 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
82 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
83 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
84 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
85 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
86 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
87 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
88 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
89 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
90 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
91 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
92 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
93 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
94 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
95 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
96 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
97 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
98 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
99 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
100 &Spell::EffectSummonWild
, // 41 SPELL_EFFECT_SUMMON_WILD
101 &Spell::EffectSummonGuardian
, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
102 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
103 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
104 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
105 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
106 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
107 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
108 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
109 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
110 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
111 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
112 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
113 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
114 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
115 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
116 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
117 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
118 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
119 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
120 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
121 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
122 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
123 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
124 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
125 &Spell::EffectUnused
, // 66 SPELL_EFFECT_POWER_FUNNEL unused
126 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
127 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
128 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
129 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
130 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
131 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
132 &Spell::EffectSummonGuardian
, // 73 SPELL_EFFECT_SUMMON_POSSESSED
133 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
134 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
135 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
136 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
137 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
138 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
139 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
140 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
141 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
142 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
143 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
144 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
145 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
146 &Spell::EffectSummonTotem
, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
147 &Spell::EffectSummonTotem
, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
148 &Spell::EffectSummonTotem
, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
149 &Spell::EffectSummonTotem
, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
150 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
151 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
152 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
153 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
154 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
155 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
156 &Spell::EffectSummonCritter
, // 97 SPELL_EFFECT_SUMMON_CRITTER
157 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
158 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
159 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
160 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
161 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
162 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
163 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
164 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
165 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
166 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
167 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
168 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
169 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
170 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
171 &Spell::EffectSummonDemon
, //112 SPELL_EFFECT_SUMMON_DEMON
172 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
173 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
174 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
175 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
176 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
177 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
178 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
179 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
180 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
181 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
182 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
183 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
184 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
185 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
186 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
187 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
188 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
189 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
190 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
191 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
192 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
193 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
194 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
195 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
196 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
197 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
198 &Spell::EffectUnused
, //139 SPELL_EFFECT_139 unused
199 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
200 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
201 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
202 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
203 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
204 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
205 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
206 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
207 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
208 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
209 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
210 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
211 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
212 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
213 &Spell::EffectNULL
, //154 unused
214 &Spell::EffectNULL
, //155 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
215 &Spell::EffectNULL
, //156 Add Socket
216 &Spell::EffectNULL
, //157 create/learn random item/spell for profession
217 &Spell::EffectMilling
, //158 milling
218 &Spell::EffectNULL
//159 allow rename pet once again
221 void Spell::EffectNULL(uint32
/*i*/)
223 sLog
.outDebug("WORLD: Spell Effect DUMMY");
226 void Spell::EffectUnused(uint32
/*i*/)
228 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
231 void Spell::EffectResurrectNew(uint32 i
)
233 if(!unitTarget
|| unitTarget
->isAlive())
236 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
239 if(!unitTarget
->IsInWorld())
242 Player
* pTarget
= ((Player
*)unitTarget
);
244 if(pTarget
->isRessurectRequested()) // already have one active request
247 uint32 health
= damage
;
248 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
249 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
250 SendResurrectRequest(pTarget
);
253 void Spell::EffectInstaKill(uint32
/*i*/)
255 if( !unitTarget
|| !unitTarget
->isAlive() )
259 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
261 uint32 entry
= unitTarget
->GetEntry();
265 case 416: spellID
=18789; break; //imp
266 case 417: spellID
=18792; break; //fellhunter
267 case 1860: spellID
=18790; break; //void
268 case 1863: spellID
=18791; break; //succubus
269 case 17252: spellID
=35701; break; //fellguard
271 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
275 m_caster
->CastSpell(m_caster
,spellID
,true);
278 if(m_caster
==unitTarget
) // prevent interrupt message
281 uint32 health
= unitTarget
->GetHealth();
282 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
285 void Spell::EffectEnvirinmentalDMG(uint32 i
)
290 // Note: this hack with damage replace required until GO casting not implemented
291 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
292 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
293 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
295 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
297 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
298 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
299 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
302 void Spell::EffectSchoolDMG(uint32 effect_idx
)
304 if( unitTarget
&& unitTarget
->isAlive())
306 switch(m_spellInfo
->SpellFamilyName
)
308 case SPELLFAMILY_GENERIC
:
311 if(m_spellInfo
->SpellIconID
== 2269 )
313 damage
+= rand()%2 ? damage
: 0;
316 switch(m_spellInfo
->Id
) // better way to check unknown
318 // Meteor like spells (divided damage to targets)
319 case 24340: case 26558: case 28884: // Meteor
320 case 36837: case 38903: case 41276: // Meteor
321 case 26789: // Shard of the Fallen Star
322 case 31436: // Malevolent Cleave
323 case 35181: // Dive Bomb
324 case 40810: case 43267: case 43268: // Saber Lash
325 case 42384: // Brutal Swipe
326 case 45150: // Meteor Slash
329 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
330 if(ihit
->effectMask
& (1<<effect_idx
))
333 damage
/= count
; // divide to all targets
336 // percent from health with min
337 case 25599: // Thundercrash
339 damage
= unitTarget
->GetHealth() / 2;
348 case SPELLFAMILY_MAGE
:
351 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
353 m_caster
->CastSpell(m_caster
,36032,true);
357 case SPELLFAMILY_WARRIOR
:
360 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
362 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
365 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
366 damage
+= int32(m_caster
->GetShieldBlockValue());
368 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
370 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
371 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
375 case SPELLFAMILY_WARLOCK
:
377 // Incinerate Rank 1 & 2
378 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
380 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
381 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
382 damage
+= int32(damage
*0.25);
386 case SPELLFAMILY_DRUID
:
389 if((m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
391 // converts each extra point of energy into ($f1+$AP/630) additional damage
392 float multiple
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 630 + m_spellInfo
->DmgMultiplier
[effect_idx
];
393 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
394 m_caster
->SetPower(POWER_ENERGY
,0);
397 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
399 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
402 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
404 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
407 else if ( m_spellInfo
->SpellFamilyFlags
& 0x0004LL
)
409 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
410 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
412 // Starfire Bonus (caster)
413 switch((*i
)->GetModifier()->m_miscvalue
)
415 case 5481: // Nordrassil Regalia - bonus
417 Unit::AuraList
const& m_periodicDamageAuras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
418 for(Unit::AuraList::const_iterator itr
= m_periodicDamageAuras
.begin(); itr
!= m_periodicDamageAuras
.end(); ++itr
)
420 // Moonfire or Insect Swarm (target debuff from any casters)
421 if ( (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x00200002LL
)
423 int32 mod
= (*i
)->GetModifier()->m_amount
;
424 damage
+= damage
*mod
/100;
430 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
432 damage
+= (*i
)->GetModifier()->m_amount
;
438 //Mangle Bonus for the initial damage of Lacerate and Rake
439 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
440 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
442 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
443 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
444 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
446 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
452 case SPELLFAMILY_ROGUE
:
455 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
457 // consume from stack dozes not more that have combo-points
458 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
460 // count consumed deadly poison doses at target
463 // remove consumed poison doses
464 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
465 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end() && combo
;)
467 // Deadly poison (only attacker applied)
468 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&& ((*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000) &&
469 (*itr
)->GetSpellProto()->SpellVisual
[0]==5100 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
474 unitTarget
->RemoveSingleAuraFromStack((*itr
)->GetId(), (*itr
)->GetEffIndex());
483 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
485 // Eviscerate and Envenom Bonus Damage (item set effect)
486 if(m_caster
->GetDummyAura(37169))
487 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
491 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
493 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
495 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * combo
* 0.03f
);
497 // Eviscerate and Envenom Bonus Damage (item set effect)
498 if(m_caster
->GetDummyAura(37169))
504 case SPELLFAMILY_HUNTER
:
507 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
509 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2);
512 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
514 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15);
517 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
519 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
520 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
522 //Explosive Trap Effect
523 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
525 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1);
529 case SPELLFAMILY_PALADIN
:
531 //Judgement of Vengeance
532 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
535 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
536 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
537 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
540 //No damage if the target isn't affected by this
552 if(m_originalCaster
) // m_caster only passive source of cast
553 finalDamage
= m_originalCaster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
555 finalDamage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
558 switch(m_spellInfo
->SpellFamilyName
)
560 case SPELLFAMILY_WARRIOR
:
563 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
566 switch(m_spellInfo
->Id
)
568 case 23881: BTAura
= 23885; break;
569 case 23892: BTAura
= 23886; break;
570 case 23893: BTAura
= 23887; break;
571 case 23894: BTAura
= 23888; break;
572 case 25251: BTAura
= 25252; break;
573 case 30335: BTAura
= 30339; break;
575 sLog
.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo
->Id
);
580 m_caster
->CastSpell(m_caster
,BTAura
,true);
584 case SPELLFAMILY_PRIEST
:
586 // Shadow Word: Death
587 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
) && unitTarget
->isAlive())
588 // deals damage equal to damage done to caster if victim is not killed
589 m_caster
->SpellNonMeleeDamageLog( m_caster
, m_spellInfo
->Id
, finalDamage
, m_IsTriggeredSpell
, false);
593 case SPELLFAMILY_PALADIN
:
595 // Judgement of Blood
596 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000800000000LL
) && m_spellInfo
->SpellIconID
==153)
598 int32 damagePoint
= finalDamage
* 33 / 100;
599 m_caster
->CastCustomSpell(m_caster
, 32220, &damagePoint
, NULL
, NULL
, true);
608 void Spell::EffectDummy(uint32 i
)
610 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
613 // selection by spell family
614 switch(m_spellInfo
->SpellFamilyName
)
616 case SPELLFAMILY_GENERIC
:
618 switch(m_spellInfo
->Id
)
620 case 8063: // Deviate Fish
622 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
628 case 1: spell_id
= 8064; break; // Sleepy
629 case 2: spell_id
= 8065; break; // Invigorate
630 case 3: spell_id
= 8066; break; // Shrink
631 case 4: spell_id
= 8067; break; // Party Time!
632 case 5: spell_id
= 8068; break; // Healthy Spirit
634 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
637 case 8213: // Savory Deviate Delight
639 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
646 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
648 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
650 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
653 case 8593: // Symbol of life (restore creature to life)
654 case 31225: // Shimmering Vessel (restore creature to life)
656 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
658 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
661 case 12162: // Deep wounds
662 case 12850: // (now good common check for this spells)
669 // DW should benefit of attack power, damage percent mods etc.
670 // TODO: check if using offhand damage is correct and if it should be divided by 2
671 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
672 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
674 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
676 switch (m_spellInfo
->Id
)
678 case 12850: damage
*= 0.2f
; break;
679 case 12162: damage
*= 0.4f
; break;
680 case 12868: damage
*= 0.6f
; break;
682 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
686 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
687 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
690 case 12975: //Last Stand
692 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
693 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
696 case 13120: // net-o-matic
703 uint32 roll
= urand(0, 99);
705 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
707 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
712 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
715 case 13567: // Dummy Trigger
717 // can be used for different aura triggering, so select by aura
718 if(!m_triggeredByAuraSpell
|| !unitTarget
)
721 switch(m_triggeredByAuraSpell
->Id
)
723 case 26467: // Persistent Shield
724 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
727 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
732 case 14185: // Preparation Rogue
734 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
737 //immediately finishes the cooldown on certain Rogue abilities
738 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
739 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
741 uint32 classspell
= itr
->first
;
742 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
744 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x26000000860LL
))
746 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
748 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
749 data
<< uint32(classspell
);
750 data
<< uint64(m_caster
->GetGUID());
751 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
756 case 15998: // Capture Worg Pup
757 case 29435: // Capture Female Kaliri Hatchling
759 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
762 Creature
* creatureTarget
= (Creature
*)unitTarget
;
763 creatureTarget
->setDeathState(JUST_DIED
);
764 creatureTarget
->RemoveCorpse();
765 creatureTarget
->SetHealth(0); // just for nice GM-mode view
768 case 16589: // Noggenfogger Elixir
770 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
776 case 1: spell_id
= 16595; break;
777 case 2: spell_id
= 16593; break;
778 default:spell_id
= 16591; break;
781 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
784 case 17251: // Spirit Healer Res
786 if(!unitTarget
|| !m_originalCaster
)
789 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
791 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
792 data
<< unitTarget
->GetGUID();
793 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
797 case 17271: // Test Fetid Skull
799 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
802 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
804 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
807 case 20577: // Cannibalize
809 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
811 case 23019: // Crystal Prison Dummy DND
813 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
816 Creature
* creatureTarget
= (Creature
*)unitTarget
;
817 if(creatureTarget
->isPet())
820 creatureTarget
->setDeathState(JUST_DIED
);
821 creatureTarget
->RemoveCorpse();
822 creatureTarget
->SetHealth(0); // just for nice GM-mode view
824 GameObject
* pGameObj
= new GameObject
;
826 Map
*map
= creatureTarget
->GetMap();
828 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
,
829 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
830 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
836 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
837 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
838 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
839 pGameObj
->SetSpellId(m_spellInfo
->Id
);
841 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
844 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
845 data
<< uint64(pGameObj
->GetGUID());
846 m_caster
->SendMessageToSet(&data
,true);
850 case 23074: // Arc. Dragonling
851 if (!m_CastItem
) return;
852 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
854 case 23075: // Mithril Mechanical Dragonling
855 if (!m_CastItem
) return;
856 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
858 case 23076: // Mechanical Dragonling
859 if (!m_CastItem
) return;
860 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
862 case 23133: // Gnomish Battle Chicken
863 if (!m_CastItem
) return;
864 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
866 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
868 int32 r
= irand(0, 119);
869 if ( r
< 20 ) // 1/6 polymorph
870 m_caster
->CastSpell(m_caster
,23444,true);
871 else if ( r
< 100 ) // 4/6 evil twin
872 m_caster
->CastSpell(m_caster
,23445,true);
873 else // 1/6 miss the target
874 m_caster
->CastSpell(m_caster
,36902,true);
877 case 23453: // Ultrasafe Transporter: Gadgetzan
878 if ( roll_chance_i(50) ) // success
879 m_caster
->CastSpell(m_caster
,23441,true);
881 m_caster
->CastSpell(m_caster
,23446,true);
883 case 23645: // Hourglass Sand
884 m_caster
->RemoveAurasDueToSpell(23170);
886 case 23725: // Gift of Life (warrior bwl trinket)
887 m_caster
->CastSpell(m_caster
,23782,true);
888 m_caster
->CastSpell(m_caster
,23783,true);
890 case 25860: // Reindeer Transformation
892 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
895 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
896 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
898 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
900 //5 different spells used depending on mounted speed and if mount can fly or not
901 if (flyspeed
>= 4.1f
)
902 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
903 else if (flyspeed
>= 3.8f
)
904 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
905 else if (flyspeed
>= 1.6f
)
906 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
907 else if (speed
>= 2.0f
)
908 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
910 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
914 //case 26074: // Holiday Cheer
915 // return; -- implemented at client side
916 case 28006: // Arcane Cloaking
918 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
919 m_caster
->CastSpell(unitTarget
,29294,true);
922 case 28730: // Arcane Torrent (Mana)
925 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
926 for(Unit::AuraList::const_iterator i
= m_dummyAuras
.begin(); i
!= m_dummyAuras
.end(); ++i
)
927 if ((*i
)->GetId() == 28734)
931 m_caster
->RemoveAurasDueToSpell(28734);
932 int32 bp
= damage
* count
;
933 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
937 case 29200: // Purify Helboar Meat
939 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
942 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
944 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
947 case 29858: // Soulshatter
948 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
949 m_caster
->CastSpell(unitTarget
,32835,true);
951 case 30458: // Nigh Invulnerability
952 if (!m_CastItem
) return;
953 if(roll_chance_i(86)) // success
954 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
955 else // backfire in 14% casts
956 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
958 case 30507: // Poultryizer
959 if (!m_CastItem
) return;
960 if(roll_chance_i(80)) // success
961 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
963 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
965 case 33060: // Make a Wish
967 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
974 case 1: spell_id
= 33053; break;
975 case 2: spell_id
= 33057; break;
976 case 3: spell_id
= 33059; break;
977 case 4: spell_id
= 33062; break;
978 case 5: spell_id
= 33064; break;
981 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
987 switch(m_caster
->GetAreaId())
989 case 3900: spell_id
= 35743; break;
990 case 3742: spell_id
= 35744; break;
994 m_caster
->CastSpell(m_caster
,spell_id
,true);
997 case 37674: // Chaos Blast
999 m_caster
->CastSpell(unitTarget
,37675,true);
1001 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1003 // selecting one from Bloodstained Fortune item
1007 case 1: newitemid
= 32688; break;
1008 case 2: newitemid
= 32689; break;
1009 case 3: newitemid
= 32690; break;
1010 case 4: newitemid
= 32691; break;
1011 case 5: newitemid
= 32692; break;
1012 case 6: newitemid
= 32693; break;
1013 case 7: newitemid
= 32700; break;
1014 case 8: newitemid
= 32701; break;
1015 case 9: newitemid
= 32702; break;
1016 case 10: newitemid
= 32703; break;
1017 case 11: newitemid
= 32704; break;
1018 case 12: newitemid
= 32705; break;
1019 case 13: newitemid
= 32706; break;
1020 case 14: newitemid
= 32707; break;
1021 case 15: newitemid
= 32708; break;
1022 case 16: newitemid
= 32709; break;
1023 case 17: newitemid
= 32710; break;
1024 case 18: newitemid
= 32711; break;
1025 case 19: newitemid
= 32712; break;
1026 case 20: newitemid
= 32713; break;
1031 DoCreateItem(i
,newitemid
);
1034 // Demon Broiled Surprise
1035 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1038 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1041 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1045 case 44875: // Complete Raptor Capture
1047 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1050 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1052 creatureTarget
->setDeathState(JUST_DIED
);
1053 creatureTarget
->RemoveCorpse();
1054 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1056 //cast spell Raptor Capture Credit
1057 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1060 case 37573: //Temporal Phase Modulator
1065 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1069 uint32 health
= tempSummon
->GetHealth();
1070 const uint32 entry_list
[6] = {21821, 21820, 21817};
1072 float x
= tempSummon
->GetPositionX();
1073 float y
= tempSummon
->GetPositionY();
1074 float z
= tempSummon
->GetPositionZ();
1075 float o
= tempSummon
->GetOrientation();
1077 tempSummon
->UnSummon();
1079 Creature
* pCreature
= m_caster
->SummonCreature(entry_list
[urand(0, 2)], x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1083 pCreature
->SetHealth(health
);
1086 pCreature
->AI()->AttackStart(m_caster
);
1090 case 34665: //Administer Antidote
1092 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1098 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1102 uint32 health
= tempSummon
->GetHealth();
1104 float x
= tempSummon
->GetPositionX();
1105 float y
= tempSummon
->GetPositionY();
1106 float z
= tempSummon
->GetPositionZ();
1107 float o
= tempSummon
->GetOrientation();
1108 tempSummon
->UnSummon();
1110 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1114 pCreature
->SetHealth(health
);
1115 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1117 if (pCreature
->AI())
1118 pCreature
->AI()->AttackStart(m_caster
);
1122 case 44997: // Converting Sentry
1124 //Converted Sentry Credit
1125 m_caster
->CastSpell(m_caster
, 45009, true);
1128 case 45030: // Impale Emissary
1130 // Emissary of Hate Credit
1131 m_caster
->CastSpell(m_caster
, 45088, true);
1134 case 50243: // Teach Language
1136 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1139 // spell has a 1/3 chance to trigger one of the below
1140 if(roll_chance_i(66))
1142 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1144 // 1000001 - gnomish binary
1145 m_caster
->CastSpell(m_caster
, 50242, true);
1149 // 01001000 - goblin binary
1150 m_caster
->CastSpell(m_caster
, 50246, true);
1155 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1157 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1160 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1161 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1163 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1168 //All IconID Check in there
1169 switch(m_spellInfo
->SpellIconID
)
1171 // Berserking (troll racial traits)
1174 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1175 int32 melee_mod
= 10;
1176 if (healthPerc
<= 40)
1178 if (healthPerc
< 100 && healthPerc
> 40)
1179 melee_mod
= 10+(100-healthPerc
)/3;
1181 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1182 int32 hasteModBasePoints1
= (5-melee_mod
);
1183 int32 hasteModBasePoints2
= 5;
1185 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1186 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1187 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1193 case SPELLFAMILY_MAGE
:
1194 switch(m_spellInfo
->Id
)
1196 case 11958: // Cold Snap
1198 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1201 // immediately finishes the cooldown on Frost spells
1202 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1203 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1205 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1208 uint32 classspell
= itr
->first
;
1209 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1211 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1212 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1213 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1215 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1217 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1218 data
<< uint32(classspell
);
1219 data
<< uint64(m_caster
->GetGUID());
1220 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1227 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1229 //Polymorph Cast Visual Rank 1
1230 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1231 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1237 case SPELLFAMILY_WARRIOR
:
1239 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1241 int32 chargeBasePoints0
= damage
;
1242 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1246 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1251 int32 basePoints0
= damage
+int32(m_caster
->GetPower(POWER_RAGE
) * m_spellInfo
->DmgMultiplier
[i
]);
1252 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1253 m_caster
->SetPower(POWER_RAGE
,0);
1256 if(m_spellInfo
->Id
==21977) //Warrior's Wrath
1261 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1265 case SPELLFAMILY_WARLOCK
:
1266 //Life Tap (only it have this with dummy effect)
1267 if (m_spellInfo
->SpellFamilyFlags
== 0x40000)
1269 float cost
= m_currentBasePoints
[0]+1;
1271 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
1272 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_COST
, cost
,this);
1274 int32 dmg
= m_caster
->SpellDamageBonus(m_caster
, m_spellInfo
,uint32(cost
> 0 ? cost
: 0), SPELL_DIRECT_DAMAGE
);
1276 if(int32(m_caster
->GetHealth()) > dmg
)
1278 // Shouldn't Appear in Combat Log
1279 m_caster
->ModifyHealth(-dmg
);
1283 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1284 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1286 // only Imp. Life Tap have this in combination with dummy aura
1287 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1288 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1291 m_caster
->CastCustomSpell(m_caster
,31818,&mana
,NULL
,NULL
,true,NULL
);
1294 int32 manaFeedVal
= m_caster
->CalculateSpellDamage(m_spellInfo
,1, m_spellInfo
->EffectBasePoints
[1],m_caster
);
1295 manaFeedVal
= manaFeedVal
* mana
/ 100;
1297 m_caster
->CastCustomSpell(m_caster
,32553,&manaFeedVal
,NULL
,NULL
,true,NULL
);
1300 SendCastResult(SPELL_FAILED_FIZZLE
);
1304 case SPELLFAMILY_PRIEST
:
1305 switch(m_spellInfo
->Id
)
1307 case 28598: // Touch of Weakness triggered spell
1309 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1313 switch(m_triggeredByAuraSpell
->Id
)
1315 case 2652: spellid
= 2943; break; // Rank 1
1316 case 19261: spellid
= 19249; break; // Rank 2
1317 case 19262: spellid
= 19251; break; // Rank 3
1318 case 19264: spellid
= 19252; break; // Rank 4
1319 case 19265: spellid
= 19253; break; // Rank 5
1320 case 19266: spellid
= 19254; break; // Rank 6
1321 case 25461: spellid
= 25460; break; // Rank 7
1323 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1326 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1331 case SPELLFAMILY_DRUID
:
1332 switch(m_spellInfo
->Id
)
1334 case 5420: // Tree of Life passive
1336 // Tree of Life area effect
1337 int32 health_mod
= int32(m_caster
->GetStat(STAT_SPIRIT
)/4);
1338 m_caster
->CastCustomSpell(m_caster
,34123,&health_mod
,NULL
,NULL
,true,NULL
);
1343 case SPELLFAMILY_ROGUE
:
1344 switch(m_spellInfo
->Id
)
1346 case 31231: // Cheat Death
1348 m_caster
->CastSpell(m_caster
,45182,true);
1353 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1356 Player
*pCaster
= ((Player
*)m_caster
);
1358 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1362 // all poison enchantments is temporary
1363 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1367 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1371 for (int s
=0;s
<3;s
++)
1373 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1376 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1377 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1380 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1383 m_caster
->CastSpell(unitTarget
, 5940, true);
1388 case SPELLFAMILY_HUNTER
:
1390 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1392 if( !unitTarget
|| !unitTarget
->isAlive())
1397 // check dazed affect
1398 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1399 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1401 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1409 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
1413 if(m_spellInfo
->SpellFamilyFlags
& 0x00080000000000LL
)
1415 if(m_caster
->getClass()!=CLASS_HUNTER
)
1418 // clear hunter crit aura state
1419 m_caster
->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE
,false);
1421 // additional damage from pet to pet target
1422 Pet
* pet
= m_caster
->GetPet();
1423 if(!pet
|| !pet
->getVictim())
1426 uint32 spell_id
= 0;
1427 switch (m_spellInfo
->Id
)
1429 case 34026: spell_id
= 34027; break; // rank 1
1431 sLog
.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo
->Id
);
1435 pet
->CastSpell(pet
->getVictim(), spell_id
, true);
1439 switch(m_spellInfo
->Id
)
1441 case 23989: //Readiness talent
1443 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1446 //immediately finishes the cooldown for hunter abilities
1447 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1448 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1450 uint32 classspell
= itr
->first
;
1451 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1453 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1455 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1457 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1458 data
<< uint32(classspell
);
1459 data
<< uint64(m_caster
->GetGUID());
1460 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1465 case 37506: // Scatter Shot
1467 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1470 // break Auto Shot and autohit
1471 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1472 m_caster
->AttackStop();
1473 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1478 case SPELLFAMILY_PALADIN
:
1479 switch(m_spellInfo
->SpellIconID
)
1481 case 156: // Holy Shock
1489 switch(m_spellInfo
->Id
)
1491 case 20473: hurt
= 25912; heal
= 25914; break;
1492 case 20929: hurt
= 25911; heal
= 25913; break;
1493 case 20930: hurt
= 25902; heal
= 25903; break;
1494 case 27174: hurt
= 27176; heal
= 27175; break;
1495 case 33072: hurt
= 33073; heal
= 33074; break;
1497 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1501 if(m_caster
->IsFriendlyTo(unitTarget
))
1502 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1504 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1508 case 561: // Judgement of command
1513 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1514 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1518 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1520 // decreased damage (/2) for non-stunned target.
1521 SpellModifier
*mod
= new SpellModifier
;
1522 mod
->op
= SPELLMOD_DAMAGE
;
1524 mod
->type
= SPELLMOD_PCT
;
1525 mod
->spellId
= m_spellInfo
->Id
;
1527 mod
->lastAffected
= NULL
;
1528 mod
->mask
= 0x0000020000000000LL
;
1531 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1532 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1534 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1537 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1543 switch(m_spellInfo
->Id
)
1545 case 31789: // Righteous Defense (step 1)
1547 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1549 // non-standard cast requirement check
1550 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1552 // clear cooldown at fail
1553 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1555 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1557 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1558 data
<< uint32(m_spellInfo
->Id
);
1559 data
<< uint64(m_caster
->GetGUID());
1560 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1563 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1567 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1568 // Clear targets for eff 1
1569 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1570 ihit
->effectMask
&= ~(1<<1);
1572 // not empty (checked)
1573 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1575 // chance to be selected from list
1576 float chance
= 100.0f
/attackers
.size();
1578 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1580 if(!roll_chance_f(chance
))
1583 AddUnitTarget((*aItr
), 1);
1586 // now let next effect cast spell at each target.
1589 case 37877: // Blessing of Faith
1594 uint32 spell_id
= 0;
1595 switch(unitTarget
->getClass())
1597 case CLASS_DRUID
: spell_id
= 37878; break;
1598 case CLASS_PALADIN
: spell_id
= 37879; break;
1599 case CLASS_PRIEST
: spell_id
= 37880; break;
1600 case CLASS_SHAMAN
: spell_id
= 37881; break;
1601 default: return; // ignore for not healing classes
1604 m_caster
->CastSpell(m_caster
,spell_id
,true);
1609 case SPELLFAMILY_SHAMAN
:
1610 //Shaman Rockbiter Weapon
1611 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1613 uint32 spell_id
= 0;
1614 switch(m_spellInfo
->Id
)
1616 case 8017: spell_id
= 36494; break; // Rank 1
1617 case 8018: spell_id
= 36750; break; // Rank 2
1618 case 8019: spell_id
= 36755; break; // Rank 3
1619 case 10399: spell_id
= 36759; break; // Rank 4
1620 case 16314: spell_id
= 36763; break; // Rank 5
1621 case 16315: spell_id
= 36766; break; // Rank 6
1622 case 16316: spell_id
= 36771; break; // Rank 7
1623 case 25479: spell_id
= 36775; break; // Rank 8
1624 case 25485: spell_id
= 36499; break; // Rank 9
1626 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1630 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1634 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1638 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1641 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1643 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1645 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1647 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1649 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1650 // at calculation applied affect from Elemental Weapons talent
1651 // real enchantment damage-1
1652 spell
->m_currentBasePoints
[1] = damage
-1;
1654 SpellCastTargets targets
;
1655 targets
.setItemTarget( item
);
1656 spell
->prepare(&targets
);
1663 if(m_spellInfo
->Id
== 39610) // Mana-Tide Totem effect
1665 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1668 // Regenerate 6% of Total Mana Every 3 secs
1669 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1670 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1678 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1680 m_caster
->AddPetAura(petSpell
);
1685 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1687 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1690 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1694 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1699 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1702 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1704 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1705 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1709 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1714 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1716 SpellCastTargets targets
;
1717 targets
.setUnitTarget( unitTarget
);
1718 spell
->prepare(&targets
);
1720 m_caster
->SetCurrentCastedSpell(spell
);
1721 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1725 void Spell::EffectForceCast(uint32 i
)
1730 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1733 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1737 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1741 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1744 void Spell::EffectTriggerSpell(uint32 i
)
1746 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1749 switch(triggered_spell_id
)
1754 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1755 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1756 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1758 // if this spell is given to NPC it must handle rest by it's own AI
1759 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1762 // get highest rank of the Stealth spell
1764 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1765 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1767 // only highest rank is shown in spell book, so simply check if shown in spell book
1768 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1771 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1775 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1777 spellId
= spellInfo
->Id
;
1782 // no Stealth spell found
1786 // reset cooldown on it if needed
1787 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1788 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1790 m_caster
->CastSpell(m_caster
, spellId
, true);
1794 case 23770: // Sayge's Dark Fortune of *
1795 // not exist, common cooldown can be implemented in scripts if need.
1797 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1800 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1804 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1805 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1808 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1811 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1815 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1816 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1819 // Righteous Defense
1822 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1828 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1829 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1831 // remove all harmful spells on you...
1832 if( // ignore positive and passive auras
1833 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1834 // ignore physical auras
1835 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 &&
1836 // ignore immunity persistent spells
1837 !( iter
->second
->GetSpellProto()->AttributesEx
& 0x10000 ) )
1839 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1840 iter
= Auras
.begin();
1845 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1848 if (Unit
*pet
= m_caster
->GetPet())
1849 pet
->CastSpell(pet
, 28305, true);
1855 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1859 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1863 // some triggered spells require specific equipment
1864 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1866 // main hand weapon required
1867 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1869 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1871 // skip spell if no weapon in slot or broken
1872 if(!item
|| item
->IsBroken() )
1875 // skip spell if weapon not fit to triggered spell
1876 if(!item
->IsFitToSpellRequirements(spellInfo
))
1880 // offhand hand weapon required
1881 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1883 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1885 // skip spell if no weapon in slot or broken
1886 if(!item
|| item
->IsBroken() )
1889 // skip spell if weapon not fit to triggered spell
1890 if(!item
->IsFitToSpellRequirements(spellInfo
))
1895 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1896 bool instant
= false;
1897 for(uint32 j
= i
+1; j
< 3; ++j
)
1899 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1909 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1912 m_TriggerSpells
.push_back(spellInfo
);
1915 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
1917 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
1920 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1924 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1925 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
1930 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
1932 Spell
*spell
= new Spell(m_caster
, spellInfo
, true, m_originalCasterGUID
);
1934 SpellCastTargets targets
;
1935 targets
.setDestination(m_targets
.m_destX
,m_targets
.m_destY
,m_targets
.m_destZ
);
1936 spell
->m_CastItem
= m_CastItem
;
1937 spell
->prepare(&targets
, NULL
);
1940 void Spell::EffectTeleportUnits(uint32 i
)
1942 if(!unitTarget
|| unitTarget
->isInFlight())
1945 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
1947 case TARGET_INNKEEPER_COORDINATES
:
1949 // Only players can teleport to innkeeper
1950 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1953 ((Player
*)unitTarget
)->TeleportTo(((Player
*)unitTarget
)->m_homebindMapId
,((Player
*)unitTarget
)->m_homebindX
,((Player
*)unitTarget
)->m_homebindY
,((Player
*)unitTarget
)->m_homebindZ
,unitTarget
->GetOrientation(),unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
1956 case TARGET_TABLE_X_Y_Z_COORDINATES
:
1958 // TODO: Only players can teleport?
1959 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1961 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
1964 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
1967 ((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);
1970 case TARGET_BEHIND_VICTIM
:
1972 // Get selected target for player (or victim for units)
1973 Unit
*pTarget
= NULL
;
1974 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1975 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
1977 pTarget
= m_caster
->getVictim();
1978 // No target present - return
1981 // Init dest coordinates
1982 uint32 mapid
= m_caster
->GetMapId();
1983 float x
= m_targets
.m_destX
;
1984 float y
= m_targets
.m_destY
;
1985 float z
= m_targets
.m_destZ
;
1986 float orientation
= pTarget
->GetOrientation();
1988 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1989 ((Player
*)unitTarget
)->TeleportTo(mapid
, x
, y
, z
, orientation
, TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
1992 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
1994 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
1995 unitTarget
->SendMessageToSet(&data
, false);
2001 // If not exist data for dest location - return
2002 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2004 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2007 // Init dest coordinates
2008 uint32 mapid
= m_caster
->GetMapId();
2009 float x
= m_targets
.m_destX
;
2010 float y
= m_targets
.m_destY
;
2011 float z
= m_targets
.m_destZ
;
2012 float orientation
= unitTarget
->GetOrientation();
2014 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2015 ((Player
*)unitTarget
)->TeleportTo(mapid
, x
, y
, z
, orientation
, TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
2018 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2020 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2021 unitTarget
->SendMessageToSet(&data
, false);
2027 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2028 switch ( m_spellInfo
->Id
)
2030 // Dimensional Ripper - Everlook
2033 int32 r
= irand(0, 119);
2034 if ( r
>= 70 ) // 7/12 success
2036 if ( r
< 100 ) // 4/12 evil twin
2037 m_caster
->CastSpell(m_caster
,23445,true);
2039 m_caster
->CastSpell(m_caster
,23449,true);
2043 // Ultrasafe Transporter: Toshley's Station
2046 if ( roll_chance_i(50) ) // 50% success
2048 int32 rand_eff
= urand(1,7);
2052 // soul split - evil
2053 m_caster
->CastSpell(m_caster
,36900,true);
2056 // soul split - good
2057 m_caster
->CastSpell(m_caster
,36901,true);
2060 // Increase the size
2061 m_caster
->CastSpell(m_caster
,36895,true);
2064 // Decrease the size
2065 m_caster
->CastSpell(m_caster
,36893,true);
2070 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2071 m_caster
->CastSpell(m_caster
,36897,true);
2073 m_caster
->CastSpell(m_caster
,36899,true);
2078 m_caster
->CastSpell(m_caster
,36940,true);
2082 m_caster
->CastSpell(m_caster
,23445,true);
2088 // Dimensional Ripper - Area 52
2091 if ( roll_chance_i(50) ) // 50% success
2093 int32 rand_eff
= urand(1,4);
2097 // soul split - evil
2098 m_caster
->CastSpell(m_caster
,36900,true);
2101 // soul split - good
2102 m_caster
->CastSpell(m_caster
,36901,true);
2105 // Increase the size
2106 m_caster
->CastSpell(m_caster
,36895,true);
2111 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2112 m_caster
->CastSpell(m_caster
,36897,true);
2114 m_caster
->CastSpell(m_caster
,36899,true);
2124 void Spell::EffectApplyAura(uint32 i
)
2129 SpellImmuneList
const& list
= unitTarget
->m_spellImmune
[IMMUNITY_STATE
];
2130 for(SpellImmuneList::const_iterator itr
= list
.begin(); itr
!= list
.end(); ++itr
)
2131 if(itr
->type
== m_spellInfo
->EffectApplyAuraName
[i
])
2134 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2135 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2136 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2139 Unit
* caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2143 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2145 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2147 // Now Reduce spell duration using data received at spell hit
2148 int32 duration
= Aur
->GetAuraMaxDuration();
2149 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2150 Aur
->setDiminishGroup(m_diminishGroup
);
2152 // if Aura removed and deleted, do not continue.
2153 if(duration
== 0 && !(Aur
->IsPermanent()))
2159 if(duration
!= Aur
->GetAuraMaxDuration())
2161 Aur
->SetAuraMaxDuration(duration
);
2162 Aur
->SetAuraDuration(duration
);
2165 bool added
= unitTarget
->AddAura(Aur
);
2167 // Aura not added and deleted in AddAura call;
2171 // found crash at character loading, broken pointer to Aur...
2172 // Aur was deleted in AddAura()...
2176 // TODO Make a way so it works for every related spell!
2177 if(unitTarget
->GetTypeId()==TYPEID_PLAYER
) // Negative buff should only be applied on players
2180 if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_WEAKENED_SOUL
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_WEAKENED_SOUL
)
2181 spellId
= 6788; // Weakened Soul
2182 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_FORBEARANCE
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_FORBEARANCE
)
2183 spellId
= 25771; // Forbearance
2184 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_HYPOTHERMIA
)
2185 spellId
= 41425; // Hypothermia
2186 else if (m_spellInfo
->Mechanic
== MECHANIC_BANDAGE
) // Bandages
2187 spellId
= 11196; // Recently Bandaged
2188 else if( (m_spellInfo
->AttributesEx
& 0x20) && (m_spellInfo
->AttributesEx2
& 0x20000) )
2189 spellId
= 23230; // Blood Fury - Healing Reduction
2191 SpellEntry
const *AdditionalSpellInfo
= sSpellStore
.LookupEntry(spellId
);
2192 if (AdditionalSpellInfo
)
2194 // applied at target by target
2195 Aura
* AdditionalAura
= CreateAura(AdditionalSpellInfo
, 0, &m_currentBasePoints
[0], unitTarget
,unitTarget
, 0);
2196 unitTarget
->AddAura(AdditionalAura
);
2197 sLog
.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo
->EffectApplyAuraName
[0]);
2201 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2202 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2203 m_caster
->CastSpell(unitTarget
,41637,true,NULL
,Aur
);
2206 void Spell::EffectUnlearnSpecialization( uint32 i
)
2208 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2211 Player
*_player
= (Player
*)unitTarget
;
2212 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2214 _player
->removeSpell(spellToUnlearn
);
2216 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2219 void Spell::EffectPowerDrain(uint32 i
)
2221 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2224 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2228 if(!unitTarget
->isAlive())
2230 if(unitTarget
->getPowerType() != drain_power
)
2235 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2237 //add spell damage bonus
2238 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2240 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2241 uint32 power
= damage
;
2242 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2243 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2246 if(curPower
< power
)
2247 new_damage
= curPower
;
2251 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2253 if(drain_power
== POWER_MANA
)
2255 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2256 if(manaMultiplier
==0)
2259 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2260 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2262 int32 gain
= int32(new_damage
*manaMultiplier
);
2264 m_caster
->ModifyPower(POWER_MANA
,gain
);
2266 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2270 void Spell::EffectSendEvent(uint32 EffectIndex
)
2272 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2274 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2275 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2277 switch(m_spellInfo
->Id
)
2279 case 23333: // Pickup Horde Flag
2280 /*do not uncomment .
2281 if(bg->GetTypeID()==BATTLEGROUND_WS)
2282 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2283 sLog.outDebug("Send Event Horde Flag Picked Up");
2286 case 23334: // Drop Horde Flag
2287 if(bg->GetTypeID()==BATTLEGROUND_WS)
2288 bg->EventPlayerDroppedFlag((Player*)m_caster);
2289 sLog.outDebug("Drop Horde Flag");
2292 case 23335: // Pickup Alliance Flag
2293 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2294 if(bg->GetTypeID()==BATTLEGROUND_WS)
2295 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2296 sLog.outDebug("Send Event Alliance Flag Picked Up");
2299 case 23336: // Drop Alliance Flag
2300 if(bg->GetTypeID()==BATTLEGROUND_WS)
2301 bg->EventPlayerDroppedFlag((Player*)m_caster);
2302 sLog.outDebug("Drop Alliance Flag");
2304 case 23385: // Alliance Flag Returns
2305 if(bg->GetTypeID()==BATTLEGROUND_WS)
2306 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2307 sLog.outDebug("Alliance Flag Returned");
2309 case 23386: // Horde Flag Returns
2310 if(bg->GetTypeID()==BATTLEGROUND_WS)
2311 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2312 sLog.outDebug("Horde Flag Returned");
2316 if(bg->GetTypeID()==BATTLEGROUND_EY)
2317 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2321 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2326 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2327 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2330 void Spell::EffectPowerBurn(uint32 i
)
2332 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2335 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2339 if(!unitTarget
->isAlive())
2341 if(unitTarget
->getPowerType()!=powertype
)
2346 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2348 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2349 uint32 power
= damage
;
2350 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2351 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2353 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2355 unitTarget
->ModifyPower(powertype
,-new_damage
);
2356 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2358 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2359 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2361 new_damage
= int32(new_damage
*multiplier
);
2362 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2365 void Spell::EffectHeal( uint32
/*i*/ )
2367 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2369 // Try to get original caster
2370 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2372 // Skip if m_originalCaster not available
2376 int32 addhealth
= damage
;
2378 // Vessel of the Naaru (Vial of the Sunwell trinket)
2379 if (m_spellInfo
->Id
== 45064)
2381 // Amount of heal - depends from stacked Holy Energy
2382 int damageAmount
= 0;
2383 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2384 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2385 if((*i
)->GetId() == 45062)
2386 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2388 m_caster
->RemoveAurasDueToSpell(45062);
2390 addhealth
+= damageAmount
;
2392 // Swiftmend - consumes Regrowth or Rejuvenation
2393 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2395 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2396 // find most short by duration
2397 Aura
*targetAura
= NULL
;
2398 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2400 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2401 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2403 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2410 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2416 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2421 int32 tickheal
= caster
->SpellHealingBonus(targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
, unitTarget
);
2422 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2423 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2425 addhealth
+= tickheal
* tickcount
;
2428 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, addhealth
,HEAL
, unitTarget
);
2430 bool crit
= caster
->isSpellCrit(unitTarget
, m_spellInfo
, m_spellSchoolMask
, m_attackType
);
2432 addhealth
= caster
->SpellCriticalBonus(m_spellInfo
, addhealth
, unitTarget
);
2433 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, crit
);
2435 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2436 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2438 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2439 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2440 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2442 // ignore item heals
2446 uint32 procHealer
= PROC_FLAG_HEAL
;
2448 procHealer
|= PROC_FLAG_CRIT_HEAL
;
2450 m_caster
->ProcDamageAndSpell(unitTarget
,procHealer
,PROC_FLAG_HEALED
,addhealth
,SPELL_SCHOOL_MASK_NONE
,m_spellInfo
,m_IsTriggeredSpell
);
2454 void Spell::EffectHealPct( uint32
/*i*/ )
2456 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2458 // Try to get original caster
2459 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2461 // Skip if m_originalCaster not available
2465 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2466 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2468 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2469 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2471 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2472 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2473 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2477 void Spell::EffectHealMechanical( uint32
/*i*/ )
2479 // Mechanic creature type should be correctly checked by targetCreatureType field
2480 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2482 // Try to get original caster
2483 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2485 // Skip if m_originalCaster not available
2489 uint32 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, uint32(damage
), HEAL
, unitTarget
);
2490 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2491 unitTarget
->ModifyHealth( int32(damage
) );
2495 void Spell::EffectHealthLeech(uint32 i
)
2499 if(!unitTarget
->isAlive())
2505 sLog
.outDebug("HealthLeech :%i", damage
);
2507 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2509 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2510 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2512 int32 new_damage
= int32(damage
*multiplier
);
2513 uint32 curHealth
= unitTarget
->GetHealth();
2514 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2515 if(curHealth
< new_damage
)
2516 new_damage
= curHealth
;
2518 if(m_caster
->isAlive())
2520 new_damage
= m_caster
->SpellHealingBonus(m_spellInfo
, new_damage
, HEAL
, m_caster
);
2522 m_caster
->ModifyHealth(new_damage
);
2524 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2525 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2529 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2531 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2534 Player
* player
= (Player
*)unitTarget
;
2536 uint32 newitemid
= itemtype
;
2537 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2540 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2546 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2547 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2549 int32 basePoints
= m_currentBasePoints
[i
];
2550 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2552 num_to_add
= basePoints
+ irand(1, randomPoints
);
2554 num_to_add
= basePoints
+ 1;
2556 else if (pProto
->MaxCount
== 1)
2558 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2560 int32 basePoints
= m_currentBasePoints
[i
];
2561 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2562 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2569 if (num_to_add
> pProto
->Stackable
)
2570 num_to_add
= pProto
->Stackable
;
2572 // init items_count to 1, since 1 item will be created regardless of specialization
2574 // the chance to create additional items
2575 float additionalCreateChance
=0.0f
;
2576 // the maximum number of created additional items
2577 uint8 additionalMaxNum
=0;
2578 // get the chance and maximum number for creating extra items
2579 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2581 // roll with this chance till we roll not to create or we create the max num
2582 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2586 // really will be created more items
2587 num_to_add
*= items_count
;
2589 // can the player store the new item?
2590 ItemPosCountVec dest
;
2591 uint32 no_space
= 0;
2592 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2593 if( msg
!= EQUIP_ERR_OK
)
2595 // convert to possible store amount
2596 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2597 num_to_add
-= no_space
;
2600 // if not created by another reason from full inventory or unique items amount limitation
2601 player
->SendEquipError( msg
, NULL
, NULL
);
2608 // create the new item and store it
2609 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2611 // was it successful? return error if not
2614 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2618 // set the "Crafted by ..." property of the item
2619 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2620 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2622 // send info to the client
2624 player
->SendNewItem(pItem
, num_to_add
, true, true);
2626 // we succeeded in creating at least one item, so a levelup is possible
2627 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2630 // for battleground marks send by mail if not add all expected
2633 BattleGroundTypeId bgType
;
2634 switch(m_spellInfo
->Id
)
2636 case SPELL_AV_MARK_WINNER
:
2637 case SPELL_AV_MARK_LOSER
:
2638 bgType
= BATTLEGROUND_AV
;
2640 case SPELL_WS_MARK_WINNER
:
2641 case SPELL_WS_MARK_LOSER
:
2642 bgType
= BATTLEGROUND_WS
;
2644 case SPELL_AB_MARK_WINNER
:
2645 case SPELL_AB_MARK_LOSER
:
2646 bgType
= BATTLEGROUND_AB
;
2652 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(bgType
))
2653 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2657 void Spell::EffectCreateItem(uint32 i
)
2659 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2662 void Spell::EffectPersistentAA(uint32 i
)
2664 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2666 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2667 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2669 int32 duration
= GetSpellDuration(m_spellInfo
);
2670 DynamicObject
* dynObj
= new DynamicObject
;
2671 if(!dynObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, i
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, radius
))
2676 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2677 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2678 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2679 m_caster
->AddDynObject(dynObj
);
2680 dynObj
->GetMap()->Add(dynObj
);
2683 void Spell::EffectEnergize(uint32 i
)
2687 if(!unitTarget
->isAlive())
2690 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2693 // Some level depends spells
2696 switch (m_spellInfo
->Id
)
2700 level_diff
= m_caster
->getLevel() - 40;
2705 level_diff
= m_caster
->getLevel() - 60;
2710 level_diff
= m_caster
->getLevel() - 60;
2718 damage
-= multiplier
* level_diff
;
2723 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2725 if(unitTarget
->GetMaxPower(power
) == 0)
2728 unitTarget
->ModifyPower(power
,damage
);
2729 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2731 // Mad Alchemist's Potion
2732 if (m_spellInfo
->Id
== 45051)
2734 // find elixirs on target
2735 uint32 elixir_mask
= 0;
2736 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2737 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2739 uint32 spell_id
= itr
->second
->GetId();
2740 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2741 elixir_mask
|= mask
;
2744 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2745 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2747 // get all available elixirs by mask and spell level
2748 std::vector
<uint32
> elixirs
;
2749 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2750 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2752 if (itr
->second
& elixir_mask
)
2754 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2757 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2758 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2761 elixirs
.push_back(itr
->first
);
2765 if (!elixirs
.empty())
2767 // cast random elixir on target
2768 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2769 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2774 void Spell::EffectEnergisePct(uint32 i
)
2778 if(!unitTarget
->isAlive())
2781 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2784 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2786 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2790 uint32 gain
= damage
* maxPower
/ 100;
2791 unitTarget
->ModifyPower(power
, gain
);
2792 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2795 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2797 Player
* player
= (Player
*)m_caster
;
2803 switch (gameObjTarget
->GetGoType())
2805 case GAMEOBJECT_TYPE_DOOR
:
2806 case GAMEOBJECT_TYPE_BUTTON
:
2807 gameObjTarget
->UseDoorOrButton();
2808 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2811 case GAMEOBJECT_TYPE_QUESTGIVER
:
2812 // start or end quest
2813 player
->PrepareQuestMenu(guid
);
2814 player
->SendPreparedQuest(guid
);
2817 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2818 // triggering linked GO
2819 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2820 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2823 case GAMEOBJECT_TYPE_GOOBER
:
2824 // goober_scripts can be triggered if the player don't have the quest
2825 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2827 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2828 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2831 // cast goober spell
2832 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2833 ///Quest require to be active for GO using
2834 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2837 gameObjTarget
->AddUniqueUse(player
);
2838 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2840 //TODO? Objective counting called without spell check but with quest objective check
2841 // if send spell id then this line will duplicate to spell casting call (double counting)
2842 // So we or have this line and not required in quest_template have reqSpellIdN
2843 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2844 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2846 // triggering linked GO
2847 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2848 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2852 case GAMEOBJECT_TYPE_CHEST
:
2853 // TODO: possible must be moved to loot release (in different from linked triggering)
2854 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2856 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2857 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2860 // triggering linked GO
2861 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2862 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2864 // Don't return, let loots been taken
2869 player
->SendLoot(guid
, loottype
);
2872 void Spell::EffectOpenLock(uint32
/*i*/)
2874 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2876 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2880 Player
* player
= (Player
*)m_caster
;
2882 LootType loottype
= LOOT_CORPSE
;
2889 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2890 // Arathi Basin banner opening !
2891 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2892 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2894 //isAllowUseBattleGroundObject() already called in CanCast()
2895 // in battleground check
2896 if(BattleGround
*bg
= player
->GetBattleGround())
2898 // check if it's correct bg
2899 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2900 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2904 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2906 //isAllowUseBattleGroundObject() already called in CanCast()
2907 // in battleground check
2908 if(BattleGround
*bg
= player
->GetBattleGround())
2910 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2911 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2915 lockId
= gameObjTarget
->GetLockId();
2916 guid
= gameObjTarget
->GetGUID();
2920 lockId
= itemTarget
->GetProto()->LockID
;
2921 guid
= itemTarget
->GetGUID();
2925 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2929 if(!lockId
) // possible case for GO and maybe for items.
2931 SendLoot(guid
, loottype
);
2936 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2940 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2941 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2942 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2947 for(int i
= 0; i
< 8; ++i
)
2949 // Type==1 This means lockInfo->Index[i] is an item
2950 if(lockInfo
->Type
[i
]==LOCK_KEY_ITEM
&& lockInfo
->Index
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->Index
[i
])
2952 SendLoot(guid
, loottype
);
2958 // Check and skill-up skill
2959 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
2960 SkillId
= m_spellInfo
->EffectMiscValue
[1];
2961 // pickpocketing spells
2962 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
2963 SkillId
= SKILL_LOCKPICKING
;
2965 // skill bonus provided by casting spell (mostly item spells)
2966 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
2968 uint32 reqSkillValue
= lockInfo
->Skill
[0];
2970 if(lockInfo
->Skill
[1]) // required pick lock skill applying
2972 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
2974 SendCastResult(SPELL_FAILED_FIZZLE
);
2978 reqSkillValue
= lockInfo
->Skill
[1];
2980 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
2982 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2988 loottype
= LOOT_SKINNING
;
2989 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
2991 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
2995 // update skill if really known
2996 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
2997 if(SkillValue
) // non only item base skill
3001 // Allow one skill-up until respawned
3002 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3003 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
3004 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3009 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3010 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
3015 SendLoot(guid
, loottype
);
3018 void Spell::EffectSummonChangeItem(uint32 i
)
3020 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3023 Player
*player
= (Player
*)m_caster
;
3025 // applied only to using item
3029 // ... only to item in own inventory/bank/equip_slot
3030 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3033 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3037 uint16 pos
= m_CastItem
->GetPos();
3039 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3043 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3045 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3046 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3049 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3051 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3052 player
->DurabilityLoss(pNewItem
, loosePercent
);
3055 if( player
->IsInventoryPos( pos
) )
3057 ItemPosCountVec dest
;
3058 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3059 if( msg
== EQUIP_ERR_OK
)
3061 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3063 // prevent crash at access and unexpected charges counting with item update queue corrupt
3064 if(m_CastItem
==m_targets
.getItemTarget())
3065 m_targets
.setItemTarget(NULL
);
3069 player
->StoreItem( dest
, pNewItem
, true);
3073 else if( player
->IsBankPos ( pos
) )
3075 ItemPosCountVec dest
;
3076 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3077 if( msg
== EQUIP_ERR_OK
)
3079 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3081 // prevent crash at access and unexpected charges counting with item update queue corrupt
3082 if(m_CastItem
==m_targets
.getItemTarget())
3083 m_targets
.setItemTarget(NULL
);
3087 player
->BankItem( dest
, pNewItem
, true);
3091 else if( player
->IsEquipmentPos ( pos
) )
3094 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3095 if( msg
== EQUIP_ERR_OK
)
3097 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3099 // prevent crash at access and unexpected charges counting with item update queue corrupt
3100 if(m_CastItem
==m_targets
.getItemTarget())
3101 m_targets
.setItemTarget(NULL
);
3105 player
->EquipItem( dest
, pNewItem
, true);
3106 player
->AutoUnequipOffhandIfNeed();
3115 void Spell::EffectOpenSecretSafe(uint32 i
)
3117 EffectOpenLock(i
); //no difference for now
3120 void Spell::EffectProficiency(uint32
/*i*/)
3122 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3124 Player
*p_target
= (Player
*)unitTarget
;
3126 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3127 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3129 p_target
->AddWeaponProficiency(subClassMask
);
3130 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3132 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3134 p_target
->AddArmorProficiency(subClassMask
);
3135 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3139 void Spell::EffectApplyAreaAura(uint32 i
)
3143 if(!unitTarget
->isAlive())
3146 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3147 unitTarget
->AddAura(Aur
);
3150 void Spell::EffectSummonType(uint32 i
)
3152 switch(m_spellInfo
->EffectMiscValueB
[i
])
3154 case SUMMON_TYPE_GUARDIAN
:
3155 case SUMMON_TYPE_POSESSED
:
3156 case SUMMON_TYPE_POSESSED2
:
3157 EffectSummonGuardian(i
);
3159 case SUMMON_TYPE_WILD
:
3160 EffectSummonWild(i
);
3162 case SUMMON_TYPE_DEMON
:
3163 EffectSummonDemon(i
);
3165 case SUMMON_TYPE_SUMMON
:
3168 case SUMMON_TYPE_CRITTER
:
3169 case SUMMON_TYPE_CRITTER2
:
3170 case SUMMON_TYPE_CRITTER3
:
3171 EffectSummonCritter(i
);
3173 case SUMMON_TYPE_TOTEM_SLOT1
:
3174 case SUMMON_TYPE_TOTEM_SLOT2
:
3175 case SUMMON_TYPE_TOTEM_SLOT3
:
3176 case SUMMON_TYPE_TOTEM_SLOT4
:
3177 case SUMMON_TYPE_TOTEM
:
3178 EffectSummonTotem(i
);
3180 case SUMMON_TYPE_UNKNOWN1
:
3181 case SUMMON_TYPE_UNKNOWN2
:
3182 case SUMMON_TYPE_UNKNOWN3
:
3183 case SUMMON_TYPE_UNKNOWN4
:
3184 case SUMMON_TYPE_UNKNOWN5
:
3187 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3192 void Spell::EffectSummon(uint32 i
)
3194 if(m_caster
->GetPetGUID())
3199 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3202 uint32 level
= m_caster
->getLevel();
3203 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3205 if(spawnCreature
->LoadPetFromDB(m_caster
,pet_entry
))
3207 // set timer for unsummon
3208 int32 duration
= GetSpellDuration(m_spellInfo
);
3210 spawnCreature
->SetDuration(duration
);
3215 Map
*map
= m_caster
->GetMap();
3216 uint32 pet_number
= objmgr
.GeneratePetNumber();
3217 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3219 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3220 delete spawnCreature
;
3224 // Summon in dest location
3226 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3228 x
= m_targets
.m_destX
;
3229 y
= m_targets
.m_destY
;
3230 z
= m_targets
.m_destZ
;
3233 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3235 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3237 if(!spawnCreature
->IsPositionValid())
3239 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3240 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3241 delete spawnCreature
;
3245 // set timer for unsummon
3246 int32 duration
= GetSpellDuration(m_spellInfo
);
3248 spawnCreature
->SetDuration(duration
);
3250 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3251 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3252 spawnCreature
->setPowerType(POWER_MANA
);
3253 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3254 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3255 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3256 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3257 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3258 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3259 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3260 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3261 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3263 spawnCreature
->InitStatsForLevel(level
);
3265 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3267 spawnCreature
->AIM_Initialize();
3268 spawnCreature
->InitPetCreateSpells();
3269 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3270 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3272 std::string name
= m_caster
->GetName();
3273 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3274 spawnCreature
->SetName( name
);
3276 map
->Add((Creature
*)spawnCreature
);
3278 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3280 m_caster
->SetPet(spawnCreature
);
3281 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3282 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3283 ((Player
*)m_caster
)->PetSpellInitialize();
3287 void Spell::EffectLearnSpell(uint32 i
)
3292 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3294 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3295 EffectLearnPetSpell(i
);
3300 Player
*player
= (Player
*)unitTarget
;
3302 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3303 player
->learnSpell(spellToLearn
);
3305 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3308 void Spell::EffectDispel(uint32 i
)
3313 // Fill possible dispell list
3314 std::vector
<Aura
*> dispel_list
;
3316 // Create dispel mask by dispel type
3317 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3318 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3319 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3320 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3322 Aura
*aur
= (*itr
).second
;
3323 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3325 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3327 bool positive
= true;
3328 if (!aur
->IsPositive())
3331 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3333 // do not remove positive auras if friendly target
3334 // negative auras if non-friendly target
3335 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3338 // Add aura to dispel list
3339 dispel_list
.push_back(aur
);
3342 // Ok if exist some buffs for dispel try dispel it
3343 if (!dispel_list
.empty())
3345 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3346 std::list
< uint32
> fail_list
; // spell_id
3347 int32 list_size
= dispel_list
.size();
3348 // Dispell N = damage buffs (or while exist buffs for dispel)
3349 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3351 // Random select buff for dispel
3352 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3354 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3355 // Base dispel chance
3356 // TODO: possible chance depend from spell level??
3357 int32 miss_chance
= 0;
3358 // Apply dispel mod from aura caster
3359 if (Unit
*caster
= aur
->GetCaster())
3361 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3362 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3365 if (roll_chance_i(miss_chance
))
3366 fail_list
.push_back(aur
->GetId());
3368 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3369 // Remove buff from list for prevent doubles
3370 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3372 Aura
*dispeled
= *j
;
3373 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3375 j
= dispel_list
.erase(j
);
3382 // Send success log and really remove auras
3383 if (!success_list
.empty())
3385 int32 count
= success_list
.size();
3386 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3387 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3388 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3389 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3390 data
<< uint8(0); // not used
3391 data
<< uint32(count
); // count
3392 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3394 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3395 data
<< uint32(spellInfo
->Id
); // Spell Id
3396 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3397 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3399 m_caster
->SendMessageToSet(&data
, true);
3403 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3405 uint32 heal_spell
= 0;
3406 switch (m_spellInfo
->Id
)
3408 case 19505: heal_spell
= 19658; break;
3409 case 19731: heal_spell
= 19732; break;
3410 case 19734: heal_spell
= 19733; break;
3411 case 19736: heal_spell
= 19735; break;
3412 case 27276: heal_spell
= 27278; break;
3413 case 27277: heal_spell
= 27279; break;
3415 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3419 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3422 // Send fail log to client
3423 if (!fail_list
.empty())
3425 // Failed to dispell
3426 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3427 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3428 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3429 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3430 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3431 data
<< uint32(*j
); // Spell Id
3432 m_caster
->SendMessageToSet(&data
, true);
3437 void Spell::EffectDualWield(uint32
/*i*/)
3439 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3440 ((Player
*)unitTarget
)->SetCanDualWield(true);
3443 void Spell::EffectPull(uint32
/*i*/)
3445 // TODO: create a proper pull towards distract spell center for distract
3446 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3449 void Spell::EffectDistract(uint32
/*i*/)
3451 // Check for possible target
3452 if (!unitTarget
|| unitTarget
->isInCombat())
3455 // target must be OK to do this
3456 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3459 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3461 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3463 // For players just turn them
3465 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3466 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3467 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3471 // Set creature Distracted, Stop it, And turn it
3472 unitTarget
->SetOrientation(angle
);
3473 unitTarget
->StopMoving();
3474 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3478 void Spell::EffectPickPocket(uint32
/*i*/)
3480 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3483 // victim must be creature and attackable
3484 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3487 // victim have to be alive and humanoid or undead
3488 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3490 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3492 if (chance
> irand(0, 19))
3494 // Stealing successful
3495 //sLog.outDebug("Sending loot from pickpocket");
3496 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3500 // Reveal action + get attack
3501 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3502 if (((Creature
*)unitTarget
)->AI())
3503 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3508 void Spell::EffectAddFarsight(uint32 i
)
3510 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3511 int32 duration
= GetSpellDuration(m_spellInfo
);
3512 DynamicObject
* dynObj
= new DynamicObject
;
3513 if(!dynObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, i
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, radius
))
3518 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3519 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3520 m_caster
->AddDynObject(dynObj
);
3521 dynObj
->GetMap()->Add(dynObj
);
3522 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3523 ((Player
*)m_caster
)->SetFarSight(dynObj
->GetGUID());
3526 void Spell::EffectSummonWild(uint32 i
)
3528 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3532 uint32 level
= m_caster
->getLevel();
3534 // level of creature summoned using engineering item based at engineering skill level
3535 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3537 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3538 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3540 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3548 // select center of summon position
3549 float center_x
= m_targets
.m_destX
;
3550 float center_y
= m_targets
.m_destY
;
3551 float center_z
= m_targets
.m_destZ
;
3553 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3555 int32 amount
= damage
> 0 ? damage
: 1;
3557 for(int32 count
= 0; count
< amount
; ++count
)
3560 // If dest location if present
3561 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3563 // Summon 1 unit in dest location
3566 px
= m_targets
.m_destX
;
3567 py
= m_targets
.m_destY
;
3568 pz
= m_targets
.m_destZ
;
3570 // Summon in random point all other units if location present
3572 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3574 // Summon if dest location not present near caster
3576 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3578 int32 duration
= GetSpellDuration(m_spellInfo
);
3580 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3582 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3586 void Spell::EffectSummonGuardian(uint32 i
)
3588 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3592 // Jewelery statue case (totem like)
3593 if(m_spellInfo
->SpellIconID
==2056)
3595 EffectSummonTotem(i
);
3599 // set timer for unsummon
3600 int32 duration
= GetSpellDuration(m_spellInfo
);
3602 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3603 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3604 // so this code hack in fact
3605 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3606 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3607 return; // find old guardian, ignore summon
3609 // in another case summon new
3610 uint32 level
= m_caster
->getLevel();
3612 // level of pet summoned using engineering item based at engineering skill level
3613 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3615 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3616 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3618 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3626 // select center of summon position
3627 float center_x
= m_targets
.m_destX
;
3628 float center_y
= m_targets
.m_destY
;
3629 float center_z
= m_targets
.m_destZ
;
3631 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3633 int32 amount
= damage
> 0 ? damage
: 1;
3635 for(int32 count
= 0; count
< amount
; ++count
)
3637 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3639 Map
*map
= m_caster
->GetMap();
3640 uint32 pet_number
= objmgr
.GeneratePetNumber();
3641 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3643 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3644 delete spawnCreature
;
3649 // If dest location if present
3650 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3652 // Summon 1 unit in dest location
3655 px
= m_targets
.m_destX
;
3656 py
= m_targets
.m_destY
;
3657 pz
= m_targets
.m_destZ
;
3659 // Summon in random point all other units if location present
3661 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3663 // Summon if dest location not present near caster
3665 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3667 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3669 if(!spawnCreature
->IsPositionValid())
3671 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3672 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3673 delete spawnCreature
;
3678 spawnCreature
->SetDuration(duration
);
3680 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3681 spawnCreature
->setPowerType(POWER_MANA
);
3682 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3683 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3684 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3685 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3686 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3687 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3688 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3690 spawnCreature
->InitStatsForLevel(level
);
3691 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3693 spawnCreature
->AIM_Initialize();
3695 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3696 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3698 map
->Add((Creature
*)spawnCreature
);
3702 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3707 if(unitTarget
->isInFlight())
3710 uint32 mapid
= m_caster
->GetMapId();
3711 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3714 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3716 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3717 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, -m_caster
->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
3719 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3722 void Spell::EffectLearnSkill(uint32 i
)
3724 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3730 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3731 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3732 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3735 void Spell::EffectAddHonor(uint32
/*i*/)
3737 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3740 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3742 // TODO: find formula for honor reward based on player's level!
3744 // now fixed only for level 70 players:
3745 if (((Player
*)unitTarget
)->getLevel() == 70)
3746 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3749 void Spell::EffectTradeSkill(uint32
/*i*/)
3751 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3753 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3754 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3755 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3758 void Spell::EffectEnchantItemPerm(uint32 i
)
3760 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3765 Player
* p_caster
= (Player
*)m_caster
;
3767 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3769 if (m_spellInfo
->EffectMiscValue
[i
])
3771 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3773 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3777 // item can be in trade slot and have owner diff. from caster
3778 Player
* item_owner
= itemTarget
->GetOwner();
3782 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3784 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3785 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3786 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3787 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3790 // remove old enchanting before applying new if equipped
3791 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3793 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3795 // add new enchanting if equipped
3796 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3800 void Spell::EffectEnchantItemTmp(uint32 i
)
3802 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3805 Player
* p_caster
= (Player
*)m_caster
;
3810 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3812 // Shaman Rockbiter Weapon
3813 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3815 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3817 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3818 // with already applied percent bonus from Elemental Weapons talent
3819 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3820 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3821 switch(enchnting_damage
)
3824 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3826 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3827 case 5: enchant_id
= 3025; break; // 20%
3829 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3830 case 7: enchant_id
= 3027; break; // 20%
3832 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3833 case 10: enchant_id
= 503; break; // 14%
3834 case 11: enchant_id
= 3031; break; // 20%
3836 case 15: enchant_id
= 3035; break; // 0%
3837 case 16: enchant_id
= 1663; break; // 7%
3838 case 17: enchant_id
= 3033; break; // 14%
3839 case 18: enchant_id
= 3034; break; // 20%
3841 case 28: enchant_id
= 3038; break; // 0%
3842 case 29: enchant_id
= 683; break; // 7%
3843 case 31: enchant_id
= 3036; break; // 14%
3844 case 33: enchant_id
= 3037; break; // 20%
3846 case 40: enchant_id
= 3041; break; // 0%
3847 case 42: enchant_id
= 1664; break; // 7%
3848 case 45: enchant_id
= 3039; break; // 14%
3849 case 48: enchant_id
= 3040; break; // 20%
3851 case 49: enchant_id
= 3044; break; // 0%
3852 case 52: enchant_id
= 2632; break; // 7%
3853 case 55: enchant_id
= 3042; break; // 14%
3854 case 58: enchant_id
= 3043; break; // 20%
3856 case 62: enchant_id
= 2633; break; // 0%
3857 case 66: enchant_id
= 3018; break; // 7%
3858 case 70: enchant_id
= 3019; break; // 14%
3859 case 74: enchant_id
= 3020; break; // 20%
3861 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3868 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3872 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3875 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3879 // select enchantment duration
3882 // rogue family enchantments exception by duration
3883 if(m_spellInfo
->Id
==38615)
3884 duration
= 1800; // 30 mins
3885 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3886 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3887 duration
= 3600; // 1 hour
3888 // shaman family enchantments
3889 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3890 duration
= 1800; // 30 mins
3891 // other cases with this SpellVisual already selected
3892 else if(m_spellInfo
->SpellVisual
[0]==215)
3893 duration
= 1800; // 30 mins
3894 // some fishing pole bonuses
3895 else if(m_spellInfo
->SpellVisual
[0]==563)
3896 duration
= 600; // 10 mins
3897 // shaman rockbiter enchantments
3898 else if(m_spellInfo
->SpellVisual
[0]==0)
3899 duration
= 1800; // 30 mins
3900 else if(m_spellInfo
->Id
==29702)
3901 duration
= 300; // 5 mins
3902 else if(m_spellInfo
->Id
==37360)
3903 duration
= 300; // 5 mins
3906 duration
= 3600; // 1 hour
3908 // item can be in trade slot and have owner diff. from caster
3909 Player
* item_owner
= itemTarget
->GetOwner();
3913 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3915 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3916 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3917 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3918 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3921 // remove old enchanting before applying new if equipped
3922 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3924 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3926 // add new enchanting if equipped
3927 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3930 void Spell::EffectTameCreature(uint32
/*i*/)
3932 if(m_caster
->GetPetGUID())
3938 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3941 Creature
* creatureTarget
= (Creature
*)unitTarget
;
3943 if(creatureTarget
->isPet())
3946 if(m_caster
->getClass() != CLASS_HUNTER
)
3949 // cast finish successfully
3950 //SendChannelUpdate(0);
3953 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
3955 // kill original creature
3956 creatureTarget
->setDeathState(JUST_DIED
);
3957 creatureTarget
->RemoveCorpse();
3958 creatureTarget
->SetHealth(0); // just for nice GM-mode view
3960 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
3962 // prepare visual effect for levelup
3963 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
3966 pet
->GetMap()->Add((Creature
*)pet
);
3968 // visual effect for levelup
3969 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
3971 // caster have pet now
3972 m_caster
->SetPet(pet
);
3974 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3976 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3977 ((Player
*)m_caster
)->PetSpellInitialize();
3981 void Spell::EffectSummonPet(uint32 i
)
3983 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
3985 Pet
*OldSummon
= m_caster
->GetPet();
3987 // if pet requested type already exist
3990 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
3992 // pet in corpse state can't be summoned
3993 if( OldSummon
->isDead() )
3996 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
3997 OldSummon
->SetMapId(m_caster
->GetMapId());
4000 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4002 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4003 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4005 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4007 ((Player
*)m_caster
)->PetSpellInitialize();
4012 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4013 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4018 Pet
* NewSummon
= new Pet
;
4020 // petentry==0 for hunter "call pet" (current pet summoned if any)
4021 if(NewSummon
->LoadPetFromDB(m_caster
,petentry
))
4023 if(NewSummon
->getPetType()==SUMMON_PET
)
4025 // Remove Demonic Sacrifice auras (known pet)
4026 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4027 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4029 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4031 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4032 itr
= auraClassScripts
.begin();
4042 // not error in case fail hunter call pet
4049 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4053 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4058 Map
*map
= m_caster
->GetMap();
4059 uint32 pet_number
= objmgr
.GeneratePetNumber();
4060 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, petentry
, pet_number
))
4067 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4069 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4071 if(!NewSummon
->IsPositionValid())
4073 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4074 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4079 uint32 petlevel
= m_caster
->getLevel();
4080 NewSummon
->setPetType(SUMMON_PET
);
4082 uint32 faction
= m_caster
->getFaction();
4083 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4085 if ( ((Creature
*)m_caster
)->isTotem() )
4086 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4088 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4091 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4092 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4093 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4094 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4095 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4096 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4097 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4098 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4099 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4100 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4102 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4103 // this enables pet details window (Shift+P)
4105 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4106 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4108 NewSummon
->InitStatsForLevel(petlevel
);
4109 NewSummon
->InitPetCreateSpells();
4111 if(NewSummon
->getPetType()==SUMMON_PET
)
4113 // Remove Demonic Sacrifice auras (new pet)
4114 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4115 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4117 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4119 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4120 itr
= auraClassScripts
.begin();
4126 // generate new name for summon pet
4127 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4128 if(!new_name
.empty())
4129 NewSummon
->SetName(new_name
);
4131 else if(NewSummon
->getPetType()==HUNTER_PET
)
4132 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4134 NewSummon
->AIM_Initialize();
4135 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4136 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4138 map
->Add((Creature
*)NewSummon
);
4140 m_caster
->SetPet(NewSummon
);
4141 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4143 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4145 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4146 ((Player
*)m_caster
)->PetSpellInitialize();
4150 void Spell::EffectLearnPetSpell(uint32 i
)
4152 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4155 Player
*_player
= (Player
*)m_caster
;
4157 Pet
*pet
= _player
->GetPet();
4163 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4164 if(!learn_spellproto
)
4167 pet
->learnSpell(learn_spellproto
->Id
);
4169 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4170 _player
->PetSpellInitialize();
4173 void Spell::EffectTaunt(uint32
/*i*/)
4175 // this effect use before aura Taunt apply for prevent taunt already attacking target
4176 // for spell as marked "non effective at already attacking target"
4177 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4179 if(unitTarget
->getVictim()==m_caster
)
4181 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4186 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4187 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4188 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4191 void Spell::EffectWeaponDmg(uint32 i
)
4195 if(!unitTarget
->isAlive())
4198 // multiple weapon dmg effect workaround
4199 // execute only the last weapon damage
4200 // and handle all effects at once
4201 for (int j
= 0; j
< 3; j
++)
4203 switch(m_spellInfo
->Effect
[j
])
4205 case SPELL_EFFECT_WEAPON_DAMAGE
:
4206 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4207 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4208 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4209 if (j
< i
) // we must calculate only at last weapon effect
4215 // some spell specific modifiers
4216 bool customBonusDamagePercentMod
= false;
4217 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4218 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4219 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4220 bool normalized
= false;
4222 int32 spell_bonus
= 0; // bonus specific for spell
4223 switch(m_spellInfo
->SpellFamilyName
)
4225 case SPELLFAMILY_WARRIOR
:
4227 // Whirlwind, single only spell with 2 weapon white damage apply if have
4228 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4230 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4231 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4233 // Devastate bonus and sunder armor refresh
4234 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4236 customBonusDamagePercentMod
= true;
4237 bonusDamagePercentMod
= 0.0f
; // only applied if auras found
4239 Unit::AuraList
const& list
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_RESISTANCE
);
4240 for(Unit::AuraList::const_iterator itr
=list
.begin();itr
!=list
.end();++itr
)
4242 SpellEntry
const *proto
= (*itr
)->GetSpellProto();
4243 if(proto
->SpellVisual
[0] == 406 && proto
->SpellIconID
== 565)
4245 int32 duration
= GetSpellDuration(proto
);
4246 (*itr
)->SetAuraDuration(duration
);
4247 (*itr
)->SendAuraUpdate(false);
4248 bonusDamagePercentMod
+= 1.0f
; // +100%
4254 case SPELLFAMILY_ROGUE
:
4257 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4259 customBonusDamagePercentMod
= true;
4260 bonusDamagePercentMod
= 2.5f
; // 250%
4262 // Mutilate (for each hand)
4263 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4267 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4272 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4273 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4275 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4284 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4288 case SPELLFAMILY_PALADIN
:
4290 // Seal of Command - receive benefit from Spell Damage and Healing
4291 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4293 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4294 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4298 case SPELLFAMILY_SHAMAN
:
4300 // Skyshatter Harness item set bonus
4302 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4304 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4305 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4307 // Stormstrike AP Buff
4308 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4310 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4318 int32 fixed_bonus
= 0;
4319 for (int j
= 0; j
< 3; j
++)
4321 switch(m_spellInfo
->Effect
[j
])
4323 case SPELL_EFFECT_WEAPON_DAMAGE
:
4324 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4325 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4327 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4328 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4331 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4332 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4334 // applied only to prev.effects fixed damage
4335 if(customBonusDamagePercentMod
)
4336 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4338 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4341 break; // not weapon damage effect, just skip
4345 // non-weapon damage
4346 int32 bonus
= spell_bonus
+ fixed_bonus
;
4348 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4352 switch(m_attackType
)
4355 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4356 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4357 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4360 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4361 bonus
= int32(bonus
*weapon_total_pct
);
4364 // + weapon damage with applied weapon% dmg to base weapon damage in call
4365 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4368 bonus
= int32(bonus
*totalDamagePercentMod
);
4370 // prevent negative damage
4371 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4373 const uint32 nohitMask
= HITINFO_ABSORB
| HITINFO_RESIST
| HITINFO_MISS
;
4376 VictimState victimState
= VICTIMSTATE_NORMAL
;
4377 uint32 blocked_dmg
= 0;
4378 uint32 absorbed_dmg
= 0;
4379 uint32 resisted_dmg
= 0;
4380 CleanDamage cleanDamage
= CleanDamage(0, BASE_ATTACK
, MELEE_HIT_NORMAL
);
4382 m_caster
->DoAttackDamage(unitTarget
, &eff_damage
, &cleanDamage
, &blocked_dmg
, m_spellSchoolMask
, &hitInfo
, &victimState
, &absorbed_dmg
, &resisted_dmg
, m_attackType
, m_spellInfo
, m_IsTriggeredSpell
);
4384 if ((hitInfo
& nohitMask
) && m_attackType
!= RANGED_ATTACK
) // not send ranged miss/etc
4385 m_caster
->SendAttackStateUpdate(hitInfo
& nohitMask
, unitTarget
, 1, m_spellSchoolMask
, eff_damage
, absorbed_dmg
, resisted_dmg
, VICTIMSTATE_NORMAL
, blocked_dmg
);
4387 bool criticalhit
= (hitInfo
& HITINFO_CRITICALHIT
);
4388 m_caster
->SendSpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, eff_damage
, m_spellSchoolMask
, absorbed_dmg
, resisted_dmg
, false, blocked_dmg
, criticalhit
);
4390 if (eff_damage
> (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
))
4392 eff_damage
-= (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
);
4396 cleanDamage
.damage
+= eff_damage
;
4400 // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4401 m_caster
->DealDamage(unitTarget
, eff_damage
, &cleanDamage
, SPELL_DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, true);
4404 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4406 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4407 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4411 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4413 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4414 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4418 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4420 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4422 // wands don't have ammo
4423 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4426 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4428 if(pItem
->GetMaxStackCount()==1)
4430 // decrease durability for non-stackable throw weapon
4431 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4435 // decrease items amount for stackable throw weapon
4437 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4440 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4441 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4445 void Spell::EffectThreat(uint32
/*i*/)
4447 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4450 if(!unitTarget
->CanHaveThreatList())
4453 unitTarget
->AddThreat(m_caster
, float(damage
));
4456 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4460 if(!unitTarget
->isAlive())
4463 uint32 heal
= m_caster
->GetMaxHealth();
4465 int32 gain
= unitTarget
->ModifyHealth(heal
);
4466 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
4468 m_caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, heal
);
4471 void Spell::EffectInterruptCast(uint32
/*i*/)
4475 if(!unitTarget
->isAlive())
4478 // TODO: not all spells that used this effect apply cooldown at school spells
4479 // also exist case: apply cooldown to interrupted cast only and to all spells
4480 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4482 if (unitTarget
->m_currentSpells
[i
])
4484 // check if we can interrupt spell
4485 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4487 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4488 unitTarget
->InterruptSpell(i
,false);
4494 void Spell::EffectSummonObjectWild(uint32 i
)
4496 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4498 GameObject
* pGameObj
= new GameObject
;
4500 WorldObject
* target
= focusObject
;
4505 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4507 x
= m_targets
.m_destX
;
4508 y
= m_targets
.m_destY
;
4509 z
= m_targets
.m_destZ
;
4512 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4514 Map
*map
= target
->GetMap();
4516 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4517 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4523 int32 duration
= GetSpellDuration(m_spellInfo
);
4524 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4525 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4527 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4528 m_caster
->AddGameObject(pGameObj
);
4531 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4533 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4535 Player
*pl
= (Player
*)m_caster
;
4536 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4537 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4539 uint32 team
= ALLIANCE
;
4541 if(pl
->GetTeam() == team
)
4544 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4549 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4551 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4553 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4554 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4556 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4561 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4563 GameObject
* linkedGO
= new GameObject
;
4564 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4565 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4567 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4568 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4570 m_caster
->AddGameObject(linkedGO
);
4582 void Spell::EffectScriptEffect(uint32 effIndex
)
4584 // TODO: we must implement hunter pet summon at login there (spell 6962)
4587 switch(m_spellInfo
->Id
)
4592 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4595 uint32 spell_id
= 0;
4598 case 1: spell_id
= 8854; break;
4599 default: spell_id
= 8855; break;
4602 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4606 // Healthstone creating spells
4616 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4617 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4619 if((*i
)->GetId() == 18692)
4624 else if((*i
)->GetId() == 18693)
4631 static uint32
const itypes
[6][3] = {
4632 { 5512,19004,19005}, // Minor Healthstone
4633 { 5511,19006,19007}, // Lesser Healthstone
4634 { 5509,19008,19009}, // Healthstone
4635 { 5510,19010,19011}, // Greater Healthstone
4636 { 9421,19012,19013}, // Major Healthstone
4637 {22103,22104,22105} // Master Healthstone
4640 switch(m_spellInfo
->Id
)
4642 case 6201: itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4643 case 6202: itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4644 case 5699: itemtype
=itypes
[2][rank
];break; // Healthstone
4645 case 11729: itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4646 case 11730: itemtype
=itypes
[4][rank
];break; // Major Healthstone
4647 case 27230: itemtype
=itypes
[5][rank
];break; // Master Healthstone
4651 DoCreateItem( effIndex
, itemtype
);
4654 // Brittle Armor - need remove one 24575 Brittle Armor aura
4656 unitTarget
->RemoveSingleAuraFromStack(24575, 0);
4657 unitTarget
->RemoveSingleAuraFromStack(24575, 1);
4659 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4661 unitTarget
->RemoveSingleAuraFromStack(26464, 0);
4663 // Orb teleport spells
4677 switch(m_spellInfo
->Id
)
4679 case 25140: spellid
= 32571; break;
4680 case 25143: spellid
= 32572; break;
4681 case 25650: spellid
= 30140; break;
4682 case 25652: spellid
= 30141; break;
4683 case 29128: spellid
= 32568; break;
4684 case 29129: spellid
= 32569; break;
4685 case 35376: spellid
= 25649; break;
4686 case 35727: spellid
= 35730; break;
4691 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4695 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4710 if(!unitTarget
|| !unitTarget
->isAlive())
4713 // Onyxia Scale Cloak
4714 if(unitTarget
->GetDummyAura(22683))
4718 m_caster
->CastSpell(unitTarget
, 22682, true);
4723 // Summon Black Qiraji Battle Tank
4729 // Prevent stacking of mounts
4730 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4732 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4733 if (unitTarget
->GetAreaId() == 3428)
4734 unitTarget
->CastSpell(unitTarget
, 25863, false);
4736 unitTarget
->CastSpell(unitTarget
, 26655, false);
4739 // Piccolo of the Flaming Fire
4742 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4744 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4753 unitTarget
->CastSpell(unitTarget
, 28694, true);
4762 // 25% chance of casting a random buff
4763 if(roll_chance_i(75))
4766 // triggered spells are 28703 to 28707
4767 // Note: some sources say, that there was the possibility of
4768 // receiving a debuff. However, this seems to be removed by a patch.
4769 const uint32 spellid
= 28703;
4771 // don't overwrite an existing aura
4772 for(uint8 i
=0; i
<5; i
++)
4773 if(unitTarget
->HasAura(spellid
+i
, 0))
4775 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
4784 // 25% chance of casting Nightmare Pollen
4785 if(roll_chance_i(75))
4787 unitTarget
->CastSpell(unitTarget
, 28721, true);
4791 // Mirren's Drinking Hat
4795 switch ( urand(1,6) )
4797 case 1: case 2: case 3: item
= 23584; break;// Loch Modan Lager
4798 case 4: case 5: item
= 23585; break;// Stouthammer Lite
4799 case 6: item
= 23586; break;// Aerie Peak Pale Ale
4802 DoCreateItem(effIndex
,item
);
4808 // Removes snares and roots.
4809 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4810 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4811 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4815 Aura
*aur
= iter
->second
;
4816 if (!aur
->IsPositive()) //only remove negative spells
4818 // check for mechanic mask
4819 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4821 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4825 next
= Auras
.begin();
4831 case 41126: // Flame Crash
4836 unitTarget
->CastSpell(unitTarget
, 41131, true);
4839 case 44876: // Force Cast - Portal Effect: Sunwell Isle
4844 unitTarget
->CastSpell(unitTarget
, 44870, true);
4848 // Goblin Weather Machine
4870 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4876 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4879 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4885 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
4887 switch(m_spellInfo
->SpellFamilyFlags
)
4892 if(!unitTarget
|| !unitTarget
->isAlive())
4894 uint32 spellId2
= 0;
4896 // all seals have aura dummy
4897 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4898 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
4900 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
4902 // search seal (all seals have judgement's aura dummy spell id in 2 effect
4903 if ( !spellInfo
|| !IsSealSpell((*itr
)->GetSpellProto()) || (*itr
)->GetEffIndex() != 2 )
4906 // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4907 spellId2
= (*itr
)->GetSpellProto()->EffectBasePoints
[2]+1;
4912 // found, remove seal
4913 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4915 // Sanctified Judgement
4916 Unit::AuraList
const& m_auras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4917 for(Unit::AuraList::const_iterator i
= m_auras
.begin(); i
!= m_auras
.end(); ++i
)
4919 if ((*i
)->GetSpellProto()->SpellIconID
== 205 && (*i
)->GetSpellProto()->Attributes
== 0x01D0LL
)
4921 int32 chance
= (*i
)->GetModifier()->m_amount
;
4922 if ( roll_chance_i(chance
) )
4924 int32 mana
= spellInfo
->manaCost
;
4925 if ( Player
* modOwner
= m_caster
->GetSpellModOwner() )
4926 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_COST
, mana
);
4927 mana
= int32(mana
* 0.8f
);
4928 m_caster
->CastCustomSpell(m_caster
,31930,&mana
,NULL
,NULL
,true,NULL
,*i
);
4937 m_caster
->CastSpell(unitTarget
,spellId2
,true);
4943 // normal DB scripted effect
4947 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
4948 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
4951 void Spell::EffectSanctuary(uint32
/*i*/)
4955 //unitTarget->CombatStop();
4957 unitTarget
->CombatStop();
4958 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
4959 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4960 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
4962 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4966 void Spell::EffectAddComboPoints(uint32
/*i*/)
4971 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4977 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
4980 void Spell::EffectDuel(uint32 i
)
4982 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4985 Player
*caster
= (Player
*)m_caster
;
4986 Player
*target
= (Player
*)unitTarget
;
4988 // caster or target already have requested duel
4989 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
4992 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
4993 // Don't have to check the target's map since you cannot challenge someone across maps
4994 uint32 mapid
= caster
->GetMapId();
4995 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
4997 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5001 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5002 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5004 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5008 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5009 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5011 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5015 //CREATE DUEL FLAG OBJECT
5016 GameObject
* pGameObj
= new GameObject
;
5018 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5020 Map
*map
= m_caster
->GetMap();
5021 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
5022 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5023 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5024 m_caster
->GetPositionZ(),
5025 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
5031 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5032 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5033 int32 duration
= GetSpellDuration(m_spellInfo
);
5034 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5035 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5037 m_caster
->AddGameObject(pGameObj
);
5042 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5043 data
<< pGameObj
->GetGUID();
5044 data
<< caster
->GetGUID();
5045 caster
->GetSession()->SendPacket(&data
);
5046 target
->GetSession()->SendPacket(&data
);
5049 DuelInfo
*duel
= new DuelInfo
;
5050 duel
->initiator
= caster
;
5051 duel
->opponent
= target
;
5052 duel
->startTime
= 0;
5053 duel
->startTimer
= 0;
5054 caster
->duel
= duel
;
5056 DuelInfo
*duel2
= new DuelInfo
;
5057 duel2
->initiator
= caster
;
5058 duel2
->opponent
= caster
;
5059 duel2
->startTime
= 0;
5060 duel2
->startTimer
= 0;
5061 target
->duel
= duel2
;
5063 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5064 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5067 void Spell::EffectStuck(uint32
/*i*/)
5069 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5072 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5075 Player
* pTarget
= (Player
*)unitTarget
;
5077 sLog
.outDebug("Spell Effect: Stuck");
5078 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());
5080 if(pTarget
->isInFlight())
5083 // homebind location is loaded always
5084 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5086 // Stuck spell trigger Hearthstone cooldown
5087 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5090 Spell
spell(pTarget
,spellInfo
,true,0);
5091 spell
.SendSpellCooldown();
5094 void Spell::EffectSummonPlayer(uint32
/*i*/)
5096 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5099 // Evil Twin (ignore player summon, but hide this for summoner)
5100 if(unitTarget
->GetDummyAura(23445))
5104 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5106 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5108 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5109 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5110 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5111 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5112 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5115 static ScriptInfo
generateActivateCommand()
5118 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5122 void Spell::EffectActivateObject(uint32 effect_idx
)
5127 static ScriptInfo activateCommand
= generateActivateCommand();
5129 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5131 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5134 void Spell::EffectApplyGlyph(uint32 i
)
5136 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5139 Player
*player
= (Player
*)m_caster
;
5142 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5144 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5146 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5147 player
->SetGlyph(m_glyphIndex
, 0);
5152 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5154 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5156 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5158 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5160 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5161 return; // glyph slot missmatch
5165 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5166 player
->SetGlyph(m_glyphIndex
, glyph
);
5168 player
->DestroyItemCount(m_CastItem
->GetEntry(), 1, true);
5173 void Spell::EffectSummonTotem(uint32 i
)
5176 switch(m_spellInfo
->EffectMiscValueB
[i
])
5178 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5179 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5180 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5181 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5182 // Battle standard case
5183 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5184 // jewelery statue case, like totem without slot
5185 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5189 if(slot
< MAX_TOTEM
)
5191 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5194 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5195 if(OldTotem
&& OldTotem
->isTotem())
5196 ((Totem
*)OldTotem
)->UnSummon();
5201 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5202 team
= ((Player
*)m_caster
)->GetTeam();
5204 Totem
* pTotem
= new Totem
;
5206 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_spellInfo
->EffectMiscValue
[i
], team
))
5212 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5215 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5217 // totem must be at same Z in case swimming caster and etc.
5218 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5219 z
= m_caster
->GetPositionZ();
5221 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5223 if(slot
< MAX_TOTEM
)
5224 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5226 pTotem
->SetOwner(m_caster
->GetGUID());
5227 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5229 int32 duration
=GetSpellDuration(m_spellInfo
);
5230 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5231 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5232 pTotem
->SetDuration(duration
);
5234 if (damage
) // if not spell info, DB values used
5236 pTotem
->SetMaxHealth(damage
);
5237 pTotem
->SetHealth(damage
);
5240 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5241 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5243 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_MOD_FEAR
,true);
5244 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_TRANSFORM
,true);
5246 pTotem
->Summon(m_caster
);
5248 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5250 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5251 data
<< uint8(slot
);
5252 data
<< uint64(pTotem
->GetGUID());
5253 data
<< uint32(duration
);
5254 data
<< uint32(m_spellInfo
->Id
);
5255 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5259 void Spell::EffectEnchantHeldItem(uint32 i
)
5261 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5262 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5265 Player
* item_owner
= (Player
*)unitTarget
;
5266 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5272 if(!item
->IsEquipped())
5275 if (m_spellInfo
->EffectMiscValue
[i
])
5277 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5278 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5280 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5282 duration
= 10; //10 seconds for enchants which don't have listed duration
5284 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5288 // Always go to temp enchantment slot
5289 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5291 // Enchantment will not be applied if a different one already exists
5292 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5295 // Apply the temporary enchantment
5296 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5297 item_owner
->ApplyEnchantment(item
,slot
,true);
5301 void Spell::EffectDisEnchant(uint32
/*i*/)
5303 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5306 Player
* p_caster
= (Player
*)m_caster
;
5307 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5310 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5312 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5314 // item will be removed at disenchanting end
5317 void Spell::EffectInebriate(uint32
/*i*/)
5319 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5322 Player
*player
= (Player
*)unitTarget
;
5323 uint16 currentDrunk
= player
->GetDrunkValue();
5324 uint16 drunkMod
= damage
* 256;
5325 if (currentDrunk
+ drunkMod
> 0xFFFF)
5326 currentDrunk
= 0xFFFF;
5328 currentDrunk
+= drunkMod
;
5329 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5332 void Spell::EffectFeedPet(uint32 i
)
5334 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5337 Player
*_player
= (Player
*)m_caster
;
5342 Pet
*pet
= _player
->GetPet();
5349 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(itemTarget
->GetProto()->ItemLevel
);
5354 _player
->DestroyItemCount(itemTarget
,count
,true);
5355 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5357 m_caster
->CastCustomSpell(m_caster
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5360 void Spell::EffectDismissPet(uint32
/*i*/)
5362 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5365 Pet
* pet
= m_caster
->GetPet();
5367 // not let dismiss dead pet
5368 if(!pet
||!pet
->isAlive())
5371 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5374 void Spell::EffectSummonObject(uint32 i
)
5376 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5379 switch(m_spellInfo
->Effect
[i
])
5381 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5382 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5383 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5384 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5388 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5391 GameObject
* obj
= NULL
;
5393 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5395 if(obj
) obj
->Delete();
5396 m_caster
->m_ObjectSlot
[slot
] = 0;
5399 GameObject
* pGameObj
= new GameObject
;
5401 float rot2
= sin(m_caster
->GetOrientation()/2);
5402 float rot3
= cos(m_caster
->GetOrientation()/2);
5405 // If dest location if present
5406 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5408 x
= m_targets
.m_destX
;
5409 y
= m_targets
.m_destY
;
5410 z
= m_targets
.m_destZ
;
5412 // Summon in random point all other units if location present
5414 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5416 Map
*map
= m_caster
->GetMap();
5417 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
, x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5423 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5424 int32 duration
= GetSpellDuration(m_spellInfo
);
5425 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5426 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5427 m_caster
->AddGameObject(pGameObj
);
5430 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5431 data
<< pGameObj
->GetGUID();
5432 m_caster
->SendMessageToSet(&data
,true);
5434 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5437 void Spell::EffectResurrect(uint32
/*effIndex*/)
5441 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5444 if(unitTarget
->isAlive())
5446 if(!unitTarget
->IsInWorld())
5449 switch (m_spellInfo
->Id
)
5451 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5453 if (roll_chance_i(67))
5455 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5459 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5461 if (roll_chance_i(50))
5463 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5471 Player
* pTarget
= ((Player
*)unitTarget
);
5473 if(pTarget
->isRessurectRequested()) // already have one active request
5476 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5477 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5479 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5480 SendResurrectRequest(pTarget
);
5483 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5485 if(!unitTarget
|| !unitTarget
->isAlive())
5488 if( unitTarget
->m_extraAttacks
)
5491 unitTarget
->m_extraAttacks
= damage
;
5494 void Spell::EffectParry(uint32
/*i*/)
5496 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5498 ((Player
*)unitTarget
)->SetCanParry(true);
5502 void Spell::EffectBlock(uint32
/*i*/)
5504 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5507 ((Player
*)unitTarget
)->SetCanBlock(true);
5510 void Spell::EffectMomentMove(uint32 i
)
5512 if(unitTarget
->isInFlight())
5515 if( m_spellInfo
->rangeIndex
== 1) //self range
5517 uint32 mapid
= m_caster
->GetMapId();
5518 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5522 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5524 unitTarget
->GetPosition(ox
,oy
,oz
);
5526 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5527 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5532 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5535 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5536 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, unitTarget
->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5538 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5542 void Spell::EffectReputation(uint32 i
)
5544 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5547 Player
*_player
= (Player
*)unitTarget
;
5549 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5551 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5553 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5558 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5561 void Spell::EffectQuestComplete(uint32 i
)
5563 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5566 Player
*_player
= (Player
*)m_caster
;
5568 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5569 _player
->AreaExploredOrEventHappens(quest_id
);
5572 void Spell::EffectSelfResurrect(uint32 i
)
5574 if(!unitTarget
|| unitTarget
->isAlive())
5576 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5578 if(!unitTarget
->IsInWorld())
5587 health
= uint32(-damage
);
5588 mana
= m_spellInfo
->EffectMiscValue
[i
];
5593 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5594 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5595 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5598 Player
*plr
= ((Player
*)unitTarget
);
5599 plr
->ResurrectPlayer(0.0f
);
5601 plr
->SetHealth( health
);
5602 plr
->SetPower(POWER_MANA
, mana
);
5603 plr
->SetPower(POWER_RAGE
, 0 );
5604 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5606 plr
->SpawnCorpseBones();
5611 void Spell::EffectSkinning(uint32
/*i*/)
5613 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5615 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5618 Creature
* creature
= (Creature
*) unitTarget
;
5619 int32 targetLevel
= creature
->getLevel();
5621 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5623 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5624 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5626 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5628 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5630 // Double chances for elites
5631 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5634 void Spell::EffectCharge(uint32
/*i*/)
5636 if(!unitTarget
|| !m_caster
)
5640 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5641 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5642 ((Creature
*)unitTarget
)->StopMoving();
5644 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5645 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5647 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5648 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5650 // not all charge effects used in negative spells
5651 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5652 m_caster
->Attack(unitTarget
,true);
5655 void Spell::EffectSummonCritter(uint32 i
)
5657 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5659 Player
* player
= (Player
*)m_caster
;
5661 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5665 Pet
* old_critter
= player
->GetMiniPet();
5667 // for same pet just despawn
5668 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5670 player
->RemoveMiniPet();
5674 // despawn old pet before summon new
5676 player
->RemoveMiniPet();
5679 Pet
* critter
= new Pet(MINI_PET
);
5681 Map
*map
= m_caster
->GetMap();
5682 uint32 pet_number
= objmgr
.GeneratePetNumber();
5683 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),
5684 map
, pet_entry
, pet_number
))
5686 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5692 // If dest location if present
5693 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5695 x
= m_targets
.m_destX
;
5696 y
= m_targets
.m_destY
;
5697 z
= m_targets
.m_destZ
;
5699 // Summon if dest location not present near caster
5701 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5703 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5705 if(!critter
->IsPositionValid())
5707 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5708 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5713 critter
->SetOwnerGUID(m_caster
->GetGUID());
5714 critter
->SetCreatorGUID(m_caster
->GetGUID());
5715 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5716 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5718 critter
->AIM_Initialize();
5719 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5720 critter
->SetMaxHealth(1);
5721 critter
->SetHealth(1);
5722 critter
->SetLevel(1);
5724 // set timer for unsummon
5725 int32 duration
= GetSpellDuration(m_spellInfo
);
5727 critter
->SetDuration(duration
);
5729 std::string name
= player
->GetName();
5730 name
.append(petTypeSuffix
[critter
->getPetType()]);
5731 critter
->SetName( name
);
5732 player
->SetMiniPet(critter
);
5734 map
->Add((Creature
*)critter
);
5737 void Spell::EffectKnockBack(uint32 i
)
5739 if(!unitTarget
|| !m_caster
)
5742 // Effect only works on players
5743 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5746 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5747 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5749 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5750 data
.append(unitTarget
->GetPackGUID());
5751 data
<< uint32(0); // Sequence
5752 data
<< float(vcos
); // x direction
5753 data
<< float(vsin
); // y direction
5754 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5755 data
<< float(damage
/-10); // Z Movement speed (vertical)
5757 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5760 void Spell::EffectSendTaxi(uint32 i
)
5762 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5765 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5769 std::vector
<uint32
> nodes
;
5772 nodes
[0] = entry
->from
;
5773 nodes
[1] = entry
->to
;
5776 switch(m_spellInfo
->Id
)
5778 case 31606: //Stormcrow Amulet
5781 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5782 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5783 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5786 case 34905: //Stealth Flight
5791 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
5795 void Spell::EffectPlayerPull(uint32 i
)
5797 if(!unitTarget
|| !m_caster
)
5800 // Effect only works on players
5801 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5804 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
5805 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
5807 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5808 data
.append(unitTarget
->GetPackGUID());
5809 data
<< uint32(0); // Sequence
5810 data
<< float(vcos
); // x direction
5811 data
<< float(vsin
); // y direction
5813 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
5814 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
5816 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5819 void Spell::EffectDispelMechanic(uint32 i
)
5824 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
5826 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5827 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
5831 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
5832 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
5834 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
5838 next
= Auras
.begin();
5844 void Spell::EffectSummonDeadPet(uint32
/*i*/)
5846 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5848 Player
*_player
= (Player
*)m_caster
;
5849 Pet
*pet
= _player
->GetPet();
5856 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
5857 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5858 pet
->setDeathState( ALIVE
);
5859 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
5860 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
5862 pet
->AIM_Initialize();
5864 _player
->PetSpellInitialize();
5865 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
5868 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
5871 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
5873 if(!m_caster
->m_TotemSlot
[slot
])
5876 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
5877 if(totem
&& totem
->isTotem())
5879 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
5880 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
5882 mana
+= spellInfo
->manaCost
* damage
/ 100;
5883 ((Totem
*)totem
)->UnSummon();
5887 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
5888 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
5891 void Spell::EffectDurabilityDamage(uint32 i
)
5893 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5896 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5898 // FIXME: some spells effects have value -1/-2
5899 // Possibly its mean -1 all player equipped items and -2 all items
5902 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
5906 // invalid slot value
5907 if(slot
>= INVENTORY_SLOT_BAG_END
)
5910 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5911 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
5914 void Spell::EffectDurabilityDamagePCT(uint32 i
)
5916 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5919 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5921 // FIXME: some spells effects have value -1/-2
5922 // Possibly its mean -1 all player equipped items and -2 all items
5925 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
5929 // invalid slot value
5930 if(slot
>= INVENTORY_SLOT_BAG_END
)
5936 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5937 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
5940 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
5945 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
5948 void Spell::EffectTransmitted(uint32 effIndex
)
5950 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
5952 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
5956 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
5962 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5964 fx
= m_targets
.m_destX
;
5965 fy
= m_targets
.m_destY
;
5966 fz
= m_targets
.m_destZ
;
5968 //FIXME: this can be better check for most objects but still hack
5969 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
5971 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
5972 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
5976 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
5977 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
5978 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
5980 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
5983 Map
*cMap
= m_caster
->GetMap();
5985 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
5987 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
5988 { // but this is not proper, we really need to ignore not materialized objects
5989 SendCastResult(SPELL_FAILED_NOT_HERE
);
5990 SendChannelUpdate(0);
5994 // replace by water level in this case
5995 fz
= cMap
->GetWaterLevel(fx
,fy
);
5997 // if gameobject is summoning object, it should be spawned right on caster's position
5998 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6000 m_caster
->GetPosition(fx
,fy
,fz
);
6003 GameObject
* pGameObj
= new GameObject
;
6005 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6006 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6012 int32 duration
= GetSpellDuration(m_spellInfo
);
6014 switch(goinfo
->type
)
6016 case GAMEOBJECT_TYPE_FISHINGNODE
:
6018 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6020 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 2, 0.88431775569915771 );
6022 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 3, -0.4668855369091033 );
6023 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6025 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6026 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6030 case 0: lastSec
= 3; break;
6031 case 1: lastSec
= 7; break;
6032 case 2: lastSec
= 13; break;
6033 case 3: lastSec
= 17; break;
6036 duration
= duration
- lastSec
*1000 + FISHING_BOBBER_READY_TIME
*1000;
6039 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6041 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6043 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6044 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6048 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6049 case GAMEOBJECT_TYPE_CHEST
:
6056 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6058 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6060 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6061 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6063 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6064 //m_caster->AddGameObject(pGameObj);
6065 //m_ObjToDel.push_back(pGameObj);
6067 cMap
->Add(pGameObj
);
6069 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6070 data
<< uint64(pGameObj
->GetGUID());
6071 m_caster
->SendMessageToSet(&data
,true);
6073 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6075 GameObject
* linkedGO
= new GameObject
;
6076 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6077 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6079 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6080 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6081 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6082 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6084 linkedGO
->GetMap()->Add(linkedGO
);
6095 void Spell::EffectProspecting(uint32
/*i*/)
6097 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6100 Player
* p_caster
= (Player
*)m_caster
;
6101 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6104 if(itemTarget
->GetCount() < 5)
6107 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6109 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6110 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6111 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6114 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6117 void Spell::EffectMilling(uint32
/*i*/)
6119 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6122 Player
* p_caster
= (Player
*)m_caster
;
6123 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6126 if(itemTarget
->GetCount() < 5)
6129 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6131 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6132 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6133 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6136 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6139 void Spell::EffectSkill(uint32
/*i*/)
6141 sLog
.outDebug("WORLD: SkillEFFECT");
6144 void Spell::EffectSummonDemon(uint32 i
)
6146 float px
= m_targets
.m_destX
;
6147 float py
= m_targets
.m_destY
;
6148 float pz
= m_targets
.m_destZ
;
6150 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6154 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6155 Charmed
->SetLevel(m_caster
->getLevel());
6157 // TODO: Add damage/mana/hp according to level
6159 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6161 // Enslave demon effect, without mana cost and cooldown
6162 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6165 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6169 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6170 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6171 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6172 This is why we use a half sec delay between the visual effect and the resurrection itself */
6173 void Spell::EffectSpiritHeal(uint32
/*i*/)
6176 if(!unitTarget || unitTarget->isAlive())
6178 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6180 if(!unitTarget->IsInWorld())
6183 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6184 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6185 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6186 ((Player*)unitTarget)->SpawnCorpseBones();
6190 // remove insignia spell effect
6191 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6193 sLog
.outDebug("Effect: SkinPlayerCorpse");
6194 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6197 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6200 void Spell::EffectStealBeneficialBuff(uint32 i
)
6202 sLog
.outDebug("Effect: StealBeneficialBuff");
6204 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6207 std::vector
<Aura
*> steal_list
;
6208 // Create dispel mask by dispel type
6209 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6210 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6211 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6213 Aura
*aur
= (*itr
).second
;
6214 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6216 // Need check for passive? this
6217 if (aur
->IsPositive() && !aur
->IsPassive())
6218 steal_list
.push_back(aur
);
6221 // Ok if exist some buffs for dispel try dispel it
6222 if (!steal_list
.empty())
6224 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6225 int32 list_size
= steal_list
.size();
6226 // Dispell N = damage buffs (or while exist buffs for dispel)
6227 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6229 // Random select buff for dispel
6230 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6231 // Not use chance for steal
6232 // TODO possible need do it
6233 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6235 // Remove buff from list for prevent doubles
6236 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6239 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6241 j
= steal_list
.erase(j
);
6248 // Really try steal and send log
6249 if (!success_list
.empty())
6251 int32 count
= success_list
.size();
6252 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6253 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6254 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6255 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6256 data
<< uint8(0); // not used
6257 data
<< uint32(count
); // count
6258 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6260 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6261 data
<< uint32(spellInfo
->Id
); // Spell Id
6262 data
<< uint8(0); // 0 - steals !=0 transfers
6263 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6265 m_caster
->SendMessageToSet(&data
, true);
6270 void Spell::EffectKillCredit(uint32 i
)
6272 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6275 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6278 void Spell::EffectQuestFail(uint32 i
)
6280 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6283 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6286 void Spell::EffectActivateRune(uint32 i
)
6288 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6291 Player
*plr
= (Player
*)m_caster
;
6293 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6296 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6298 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[i
])
6300 plr
->SetRuneCooldown(j
, 0));