2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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"
56 #include "ScriptCalls.h"
57 #include "SkillDiscovery.h"
59 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
61 &Spell::EffectNULL
, // 0
62 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
63 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
64 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
65 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
66 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
67 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
68 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
69 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
70 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
71 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
72 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
73 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
74 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
75 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
76 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
77 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
78 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
79 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
80 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
81 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
82 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
83 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
84 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
85 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
86 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
87 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
88 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
89 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
90 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
91 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
92 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
93 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
94 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
95 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
96 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
97 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
98 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
99 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
100 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
101 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
102 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
103 &Spell::EffectUnused
, // 42 SPELL_EFFECT_JUMP2
104 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
105 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
106 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
107 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
108 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
109 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
110 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
111 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
112 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
113 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
114 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
115 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
116 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
117 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
118 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
119 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
120 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
121 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
122 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
123 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
124 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
125 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
126 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
127 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
128 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
129 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
130 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
131 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
132 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
133 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
134 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
135 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
136 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
137 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
138 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
139 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
140 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
141 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
142 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
143 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
144 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
145 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
146 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
147 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
148 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
149 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
150 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
151 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
152 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
153 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
154 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
155 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
156 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
157 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
158 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
159 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
160 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
161 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
162 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
163 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
164 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
165 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
166 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
167 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
168 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
169 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
170 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
171 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
172 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
173 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
174 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
175 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
176 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
177 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
178 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
179 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
180 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
181 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
182 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
183 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
184 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
185 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
186 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
187 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
188 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
189 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
190 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
191 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
192 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
193 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
194 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
195 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
196 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
197 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
198 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
199 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
200 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
201 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
202 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
203 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
204 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
205 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
206 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
207 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
208 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
209 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
210 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
211 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
212 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
213 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
214 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
215 &Spell::EffectNULL
, //154 unused
216 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
217 &Spell::EffectNULL
, //156 Add Socket
218 &Spell::EffectCreateItem
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
219 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
220 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
223 void Spell::EffectNULL(uint32
/*i*/)
225 sLog
.outDebug("WORLD: Spell Effect DUMMY");
228 void Spell::EffectUnused(uint32
/*i*/)
230 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
233 void Spell::EffectResurrectNew(uint32 i
)
235 if(!unitTarget
|| unitTarget
->isAlive())
238 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
241 if(!unitTarget
->IsInWorld())
244 Player
* pTarget
= ((Player
*)unitTarget
);
246 if(pTarget
->isRessurectRequested()) // already have one active request
249 uint32 health
= damage
;
250 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
251 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
252 SendResurrectRequest(pTarget
);
255 void Spell::EffectInstaKill(uint32
/*i*/)
257 if( !unitTarget
|| !unitTarget
->isAlive() )
261 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
263 uint32 entry
= unitTarget
->GetEntry();
267 case 416: spellID
=18789; break; //imp
268 case 417: spellID
=18792; break; //fellhunter
269 case 1860: spellID
=18790; break; //void
270 case 1863: spellID
=18791; break; //succubus
271 case 17252: spellID
=35701; break; //fellguard
273 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
277 m_caster
->CastSpell(m_caster
,spellID
,true);
280 if(m_caster
==unitTarget
) // prevent interrupt message
283 uint32 health
= unitTarget
->GetHealth();
284 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
287 void Spell::EffectEnvirinmentalDMG(uint32 i
)
292 // Note: this hack with damage replace required until GO casting not implemented
293 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
294 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
295 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
297 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
299 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
300 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
301 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
304 void Spell::EffectSchoolDMG(uint32 effect_idx
)
306 if( unitTarget
&& unitTarget
->isAlive())
308 switch(m_spellInfo
->SpellFamilyName
)
310 case SPELLFAMILY_GENERIC
:
313 if(m_spellInfo
->SpellIconID
== 2269 )
315 damage
+= rand()%2 ? damage
: 0;
318 switch(m_spellInfo
->Id
) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
331 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
332 if(ihit
->effectMask
& (1<<effect_idx
))
335 damage
/= count
; // divide to all targets
338 // percent from health with min
339 case 25599: // Thundercrash
341 damage
= unitTarget
->GetHealth() / 2;
346 // Intercept (warrior spell trigger)
350 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
357 case SPELLFAMILY_MAGE
:
360 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
362 m_caster
->CastSpell(m_caster
,36032,true);
366 case SPELLFAMILY_WARRIOR
:
369 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
371 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
374 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
375 damage
+= int32(m_caster
->GetShieldBlockValue());
377 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
379 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
380 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
382 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
383 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
384 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
385 // Heroic Throw ${$m1+$AP*.50}
386 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
387 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
388 // Shockwave ${$m3/100*$AP}
389 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
391 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
393 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
398 case SPELLFAMILY_WARLOCK
:
400 // Incinerate Rank 1 & 2
401 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
403 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
404 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
405 damage
+= int32(damage
*0.25f
);
409 case SPELLFAMILY_PRIEST
:
411 // Shadow Word: Death - deals damage equal to damage done to caster
412 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
413 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
416 case SPELLFAMILY_DRUID
:
419 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
421 // converts each extra point of energy into ($f1+$AP/410) additional damage
422 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
423 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
424 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
425 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
426 m_caster
->SetPower(POWER_ENERGY
,0);
429 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
431 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
434 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
436 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
439 else if ( m_spellInfo
->SpellFamilyFlags
& 0x0004LL
)
441 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
442 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
444 // Starfire Bonus (caster)
445 switch((*i
)->GetModifier()->m_miscvalue
)
447 case 5481: // Nordrassil Regalia - bonus
449 Unit::AuraList
const& m_periodicDamageAuras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
450 for(Unit::AuraList::const_iterator itr
= m_periodicDamageAuras
.begin(); itr
!= m_periodicDamageAuras
.end(); ++itr
)
452 // Moonfire or Insect Swarm (target debuff from any casters)
453 if ( (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x00200002LL
)
455 int32 mod
= (*i
)->GetModifier()->m_amount
;
456 damage
+= damage
*mod
/100;
462 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
464 damage
+= (*i
)->GetModifier()->m_amount
;
470 //Mangle Bonus for the initial damage of Lacerate and Rake
471 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
472 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
474 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
475 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
476 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
478 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
484 case SPELLFAMILY_ROGUE
:
487 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
489 // consume from stack dozes not more that have combo-points
490 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
493 // Lookup for Deadly poison (only attacker applied)
494 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
495 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
496 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
497 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
498 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
503 // count consumed deadly poison doses at target
506 uint32 spellId
= poison
->GetId();
507 uint32 doses
= poison
->GetStackAmount();
510 for (int i
=0; i
< doses
; i
++)
511 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
513 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
515 // Eviscerate and Envenom Bonus Damage (item set effect)
516 if(m_caster
->GetDummyAura(37169))
517 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
521 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
523 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
525 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
526 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
528 // Eviscerate and Envenom Bonus Damage (item set effect)
529 if(m_caster
->GetDummyAura(37169))
534 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
536 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
539 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
541 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
544 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
546 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
550 case SPELLFAMILY_HUNTER
:
553 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
555 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
558 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
560 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
563 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
565 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
568 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
570 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
571 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
573 // Explosive Trap Effect
574 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
576 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
580 case SPELLFAMILY_PALADIN
:
582 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
583 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
585 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
586 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
587 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
588 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
589 // Get stack of Holy Vengeance on the target added by caster
591 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
592 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
593 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
595 stacks
= (*itr
)->GetStackAmount();
598 // + 10% for each application of Holy Vengeance on the target
600 damage
+= damage
* stacks
* 10 /100;
602 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP)
603 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
605 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
606 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
607 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
608 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
610 // Exorcism ($m1+0.15*$SPH+0.15*$AP)
611 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
613 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
614 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
615 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
616 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
618 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP)
619 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
621 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
622 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
623 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
624 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
626 // Holy Wrath ($m1+0.07*$SPH+0.07*$AP)
627 else if(m_spellInfo
->SpellFamilyFlags
& 0x0020000000000000LL
)
629 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
630 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
631 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
632 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
643 void Spell::EffectDummy(uint32 i
)
645 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
648 // selection by spell family
649 switch(m_spellInfo
->SpellFamilyName
)
651 case SPELLFAMILY_GENERIC
:
653 switch(m_spellInfo
->Id
)
655 case 8063: // Deviate Fish
657 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
663 case 1: spell_id
= 8064; break; // Sleepy
664 case 2: spell_id
= 8065; break; // Invigorate
665 case 3: spell_id
= 8066; break; // Shrink
666 case 4: spell_id
= 8067; break; // Party Time!
667 case 5: spell_id
= 8068; break; // Healthy Spirit
669 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
672 case 8213: // Savory Deviate Delight
674 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
681 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
683 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
685 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
688 case 8593: // Symbol of life (restore creature to life)
689 case 31225: // Shimmering Vessel (restore creature to life)
691 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
693 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
696 case 12162: // Deep wounds
697 case 12850: // (now good common check for this spells)
704 // DW should benefit of attack power, damage percent mods etc.
705 // TODO: check if using offhand damage is correct and if it should be divided by 2
706 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
707 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
709 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
711 switch (m_spellInfo
->Id
)
713 case 12850: damage
*= 0.2f
; break;
714 case 12162: damage
*= 0.4f
; break;
715 case 12868: damage
*= 0.6f
; break;
717 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
721 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
722 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
725 case 13120: // net-o-matic
732 uint32 roll
= urand(0, 99);
734 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
736 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
741 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
744 case 13567: // Dummy Trigger
746 // can be used for different aura triggering, so select by aura
747 if(!m_triggeredByAuraSpell
|| !unitTarget
)
750 switch(m_triggeredByAuraSpell
->Id
)
752 case 26467: // Persistent Shield
753 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
756 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
761 case 15998: // Capture Worg Pup
762 case 29435: // Capture Female Kaliri Hatchling
764 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
767 Creature
* creatureTarget
= (Creature
*)unitTarget
;
768 creatureTarget
->setDeathState(JUST_DIED
);
769 creatureTarget
->RemoveCorpse();
770 creatureTarget
->SetHealth(0); // just for nice GM-mode view
773 case 16589: // Noggenfogger Elixir
775 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
781 case 1: spell_id
= 16595; break;
782 case 2: spell_id
= 16593; break;
783 default:spell_id
= 16591; break;
786 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
789 case 17251: // Spirit Healer Res
791 if(!unitTarget
|| !m_originalCaster
)
794 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
796 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
797 data
<< unitTarget
->GetGUID();
798 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
802 case 17271: // Test Fetid Skull
804 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
807 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
809 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
812 case 20577: // Cannibalize
814 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
816 case 23019: // Crystal Prison Dummy DND
818 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
821 Creature
* creatureTarget
= (Creature
*)unitTarget
;
822 if(creatureTarget
->isPet())
825 creatureTarget
->setDeathState(JUST_DIED
);
826 creatureTarget
->RemoveCorpse();
827 creatureTarget
->SetHealth(0); // just for nice GM-mode view
829 GameObject
* pGameObj
= new GameObject
;
831 Map
*map
= creatureTarget
->GetMap();
833 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
,
834 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
835 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
841 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
842 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
843 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
844 pGameObj
->SetSpellId(m_spellInfo
->Id
);
846 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
849 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
850 data
<< uint64(pGameObj
->GetGUID());
851 m_caster
->SendMessageToSet(&data
,true);
855 case 23074: // Arcanite Dragonling
856 if (!m_CastItem
) return;
857 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
859 case 23075: // Mithril Mechanical Dragonling
860 if (!m_CastItem
) return;
861 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
863 case 23076: // Mechanical Dragonling
864 if (!m_CastItem
) return;
865 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
867 case 23133: // Gnomish Battle Chicken
868 if (!m_CastItem
) return;
869 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
871 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
873 int32 r
= irand(0, 119);
874 if ( r
< 20 ) // 1/6 polymorph
875 m_caster
->CastSpell(m_caster
,23444,true);
876 else if ( r
< 100 ) // 4/6 evil twin
877 m_caster
->CastSpell(m_caster
,23445,true);
878 else // 1/6 miss the target
879 m_caster
->CastSpell(m_caster
,36902,true);
882 case 23453: // Ultrasafe Transporter: Gadgetzan
883 if ( roll_chance_i(50) ) // success
884 m_caster
->CastSpell(m_caster
,23441,true);
886 m_caster
->CastSpell(m_caster
,23446,true);
888 case 23645: // Hourglass Sand
889 m_caster
->RemoveAurasDueToSpell(23170);
891 case 23725: // Gift of Life (warrior bwl trinket)
892 m_caster
->CastSpell(m_caster
,23782,true);
893 m_caster
->CastSpell(m_caster
,23783,true);
895 case 25860: // Reindeer Transformation
897 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
900 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
901 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
903 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
905 //5 different spells used depending on mounted speed and if mount can fly or not
906 if (flyspeed
>= 4.1f
)
907 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
908 else if (flyspeed
>= 3.8f
)
909 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
910 else if (flyspeed
>= 1.6f
)
911 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
912 else if (speed
>= 2.0f
)
913 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
915 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
919 //case 26074: // Holiday Cheer
920 // return; -- implemented at client side
921 case 28006: // Arcane Cloaking
923 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
924 m_caster
->CastSpell(unitTarget
,29294,true);
927 case 28730: // Arcane Torrent (Mana)
929 Aura
* dummy
= m_caster
->GetDummyAura(28734);
932 int32 bp
= damage
* dummy
->GetStackAmount();
933 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
934 m_caster
->RemoveAurasDueToSpell(28734);
938 case 29200: // Purify Helboar Meat
940 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
943 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
945 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
948 case 29858: // Soulshatter
949 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
950 m_caster
->CastSpell(unitTarget
,32835,true);
952 case 30458: // Nigh Invulnerability
953 if (!m_CastItem
) return;
954 if(roll_chance_i(86)) // success
955 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
956 else // backfire in 14% casts
957 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
959 case 30507: // Poultryizer
960 if (!m_CastItem
) return;
961 if(roll_chance_i(80)) // success
962 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
964 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
966 case 33060: // Make a Wish
968 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
975 case 1: spell_id
= 33053; break;
976 case 2: spell_id
= 33057; break;
977 case 3: spell_id
= 33059; break;
978 case 4: spell_id
= 33062; break;
979 case 5: spell_id
= 33064; break;
982 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
988 switch(m_caster
->GetAreaId())
990 case 3900: spell_id
= 35743; break;
991 case 3742: spell_id
= 35744; break;
995 m_caster
->CastSpell(m_caster
,spell_id
,true);
998 case 37674: // Chaos Blast
1003 int32 basepoints0
= 100;
1004 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
1007 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1009 // selecting one from Bloodstained Fortune item
1013 case 1: newitemid
= 32688; break;
1014 case 2: newitemid
= 32689; break;
1015 case 3: newitemid
= 32690; break;
1016 case 4: newitemid
= 32691; break;
1017 case 5: newitemid
= 32692; break;
1018 case 6: newitemid
= 32693; break;
1019 case 7: newitemid
= 32700; break;
1020 case 8: newitemid
= 32701; break;
1021 case 9: newitemid
= 32702; break;
1022 case 10: newitemid
= 32703; break;
1023 case 11: newitemid
= 32704; break;
1024 case 12: newitemid
= 32705; break;
1025 case 13: newitemid
= 32706; break;
1026 case 14: newitemid
= 32707; break;
1027 case 15: newitemid
= 32708; break;
1028 case 16: newitemid
= 32709; break;
1029 case 17: newitemid
= 32710; break;
1030 case 18: newitemid
= 32711; break;
1031 case 19: newitemid
= 32712; break;
1032 case 20: newitemid
= 32713; break;
1037 DoCreateItem(i
,newitemid
);
1040 // Demon Broiled Surprise
1041 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1044 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1047 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1051 case 44875: // Complete Raptor Capture
1053 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1056 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1058 creatureTarget
->setDeathState(JUST_DIED
);
1059 creatureTarget
->RemoveCorpse();
1060 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1062 //cast spell Raptor Capture Credit
1063 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1066 case 37573: //Temporal Phase Modulator
1071 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1075 uint32 health
= tempSummon
->GetHealth();
1076 const uint32 entry_list
[6] = {21821, 21820, 21817};
1078 float x
= tempSummon
->GetPositionX();
1079 float y
= tempSummon
->GetPositionY();
1080 float z
= tempSummon
->GetPositionZ();
1081 float o
= tempSummon
->GetOrientation();
1083 tempSummon
->UnSummon();
1085 Creature
* pCreature
= m_caster
->SummonCreature(entry_list
[urand(0, 2)], x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1089 pCreature
->SetHealth(health
);
1092 pCreature
->AI()->AttackStart(m_caster
);
1096 case 34665: //Administer Antidote
1098 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1104 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1108 uint32 health
= tempSummon
->GetHealth();
1110 float x
= tempSummon
->GetPositionX();
1111 float y
= tempSummon
->GetPositionY();
1112 float z
= tempSummon
->GetPositionZ();
1113 float o
= tempSummon
->GetOrientation();
1114 tempSummon
->UnSummon();
1116 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1120 pCreature
->SetHealth(health
);
1121 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1123 if (pCreature
->AI())
1124 pCreature
->AI()->AttackStart(m_caster
);
1128 case 44997: // Converting Sentry
1130 //Converted Sentry Credit
1131 m_caster
->CastSpell(m_caster
, 45009, true);
1134 case 45030: // Impale Emissary
1136 // Emissary of Hate Credit
1137 m_caster
->CastSpell(m_caster
, 45088, true);
1140 case 50243: // Teach Language
1142 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1145 // spell has a 1/3 chance to trigger one of the below
1146 if(roll_chance_i(66))
1148 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1150 // 1000001 - gnomish binary
1151 m_caster
->CastSpell(m_caster
, 50242, true);
1155 // 01001000 - goblin binary
1156 m_caster
->CastSpell(m_caster
, 50246, true);
1161 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1163 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1166 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1167 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1169 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1175 m_caster
->CastSpell(m_caster
,54586,true);
1180 //All IconID Check in there
1181 switch(m_spellInfo
->SpellIconID
)
1183 // Berserking (troll racial traits)
1186 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1187 int32 melee_mod
= 10;
1188 if (healthPerc
<= 40)
1190 if (healthPerc
< 100 && healthPerc
> 40)
1191 melee_mod
= 10+(100-healthPerc
)/3;
1193 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1194 int32 hasteModBasePoints1
= (5-melee_mod
);
1195 int32 hasteModBasePoints2
= 5;
1197 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1198 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1199 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1205 case SPELLFAMILY_MAGE
:
1206 switch(m_spellInfo
->Id
)
1208 case 11958: // Cold Snap
1210 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1213 // immediately finishes the cooldown on Frost spells
1214 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1215 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1217 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1220 uint32 classspell
= itr
->first
;
1221 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1223 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1224 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1225 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1227 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1229 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1230 data
<< uint32(classspell
);
1231 data
<< uint64(m_caster
->GetGUID());
1232 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1239 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1241 //Polymorph Cast Visual Rank 1
1242 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1243 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1249 case SPELLFAMILY_WARRIOR
:
1251 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1253 int32 chargeBasePoints0
= damage
;
1254 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1258 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1263 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1264 // Glyph of Execution bonus
1265 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1266 rage
+=aura
->GetModifier()->m_amount
;
1268 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1269 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1270 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1271 m_caster
->SetPower(POWER_RAGE
,0);
1274 switch(m_spellInfo
->Id
)
1281 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1287 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1288 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1294 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1299 case SPELLFAMILY_WARLOCK
:
1301 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1303 // In 303 exist spirit depend
1304 uint32 spirit
= m_caster
->GetStat(STAT_SPIRIT
);
1305 switch (m_spellInfo
->Id
)
1307 case 1454: damage
+=spirit
; break;
1308 case 1455: damage
+=spirit
*15/10; break;
1309 case 1456: damage
+=spirit
*2; break;
1310 case 11687: damage
+=spirit
*25/10; break;
1314 case 57946: damage
+=spirit
*3; break;
1316 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1319 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1320 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1321 if(int32(unitTarget
->GetHealth()) > damage
)
1323 // Shouldn't Appear in Combat Log
1324 unitTarget
->ModifyHealth(-damage
);
1326 int32 mana
= damage
;
1327 // Improved Life Tap mod
1328 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1329 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1331 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1332 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1334 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1337 int32 manaFeedVal
= 0;
1338 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1339 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1341 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1342 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1346 manaFeedVal
= manaFeedVal
* mana
/ 100;
1347 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1351 SendCastResult(SPELL_FAILED_FIZZLE
);
1355 case SPELLFAMILY_PRIEST
:
1357 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1364 switch(m_spellInfo
->Id
)
1366 case 47540: hurt
= 47758; heal
= 47757; break;
1367 case 53005: hurt
= 53001; heal
= 52986; break;
1368 case 53006: hurt
= 53002; heal
= 52987; break;
1369 case 53007: hurt
= 53003; heal
= 52988; break;
1371 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1374 if (m_caster
->IsFriendlyTo(unitTarget
))
1375 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1377 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1380 switch(m_spellInfo
->Id
)
1382 case 28598: // Touch of Weakness triggered spell
1384 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1388 switch(m_triggeredByAuraSpell
->Id
)
1390 case 2652: spellid
= 2943; break; // Rank 1
1391 case 19261: spellid
= 19249; break; // Rank 2
1392 case 19262: spellid
= 19251; break; // Rank 3
1393 case 19264: spellid
= 19252; break; // Rank 4
1394 case 19265: spellid
= 19253; break; // Rank 5
1395 case 19266: spellid
= 19254; break; // Rank 6
1396 case 25461: spellid
= 25460; break; // Rank 7
1398 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1401 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1406 case SPELLFAMILY_DRUID
:
1408 case SPELLFAMILY_ROGUE
:
1409 switch(m_spellInfo
->Id
)
1413 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1416 Player
*pCaster
= ((Player
*)m_caster
);
1418 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1422 // all poison enchantments is temporary
1423 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1427 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1431 for (int s
=0;s
<3;s
++)
1433 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1436 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1437 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1440 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1443 m_caster
->CastSpell(unitTarget
, 5940, true);
1446 case 14185: // Preparation Rogue
1448 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1451 //immediately finishes the cooldown on certain Rogue abilities
1452 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1453 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1455 uint32 classspell
= itr
->first
;
1456 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1458 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1460 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1462 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1463 data
<< uint32(classspell
);
1464 data
<< uint64(m_caster
->GetGUID());
1465 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1470 case 31231: // Cheat Death
1472 m_caster
->CastSpell(m_caster
,45182,true);
1477 case SPELLFAMILY_HUNTER
:
1479 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1481 if( !unitTarget
|| !unitTarget
->isAlive())
1486 // check dazed affect
1487 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1488 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1490 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1502 switch(m_spellInfo
->Id
)
1504 case 23989: //Readiness talent
1506 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1509 //immediately finishes the cooldown for hunter abilities
1510 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1511 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1513 uint32 classspell
= itr
->first
;
1514 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1516 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1518 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1520 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1521 data
<< uint32(classspell
);
1522 data
<< uint64(m_caster
->GetGUID());
1523 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1528 case 37506: // Scatter Shot
1530 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1533 // break Auto Shot and autohit
1534 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1535 m_caster
->AttackStop();
1536 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1541 case SPELLFAMILY_PALADIN
:
1542 switch(m_spellInfo
->SpellIconID
)
1544 case 156: // Holy Shock
1552 switch(m_spellInfo
->Id
)
1554 case 20473: hurt
= 25912; heal
= 25914; break;
1555 case 20929: hurt
= 25911; heal
= 25913; break;
1556 case 20930: hurt
= 25902; heal
= 25903; break;
1557 case 27174: hurt
= 27176; heal
= 27175; break;
1558 case 33072: hurt
= 33073; heal
= 33074; break;
1559 case 48824: hurt
= 48822; heal
= 48820; break;
1560 case 48825: hurt
= 48823; heal
= 48821; break;
1562 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1566 if(m_caster
->IsFriendlyTo(unitTarget
))
1567 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1569 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1573 case 561: // Judgement of command
1578 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1579 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1583 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1585 // decreased damage (/2) for non-stunned target.
1586 SpellModifier
*mod
= new SpellModifier
;
1587 mod
->op
= SPELLMOD_DAMAGE
;
1589 mod
->type
= SPELLMOD_PCT
;
1590 mod
->spellId
= m_spellInfo
->Id
;
1591 mod
->mask
= 0x0000020000000000LL
;
1594 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1595 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1597 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1600 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1606 switch(m_spellInfo
->Id
)
1608 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1613 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1616 case 31789: // Righteous Defense (step 1)
1618 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1620 // non-standard cast requirement check
1621 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1623 // clear cooldown at fail
1624 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1626 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1628 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1629 data
<< uint32(m_spellInfo
->Id
);
1630 data
<< uint64(m_caster
->GetGUID());
1631 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1634 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1638 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1639 // Clear targets for eff 1
1640 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1641 ihit
->effectMask
&= ~(1<<1);
1643 // not empty (checked)
1644 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1646 // chance to be selected from list
1647 float chance
= 100.0f
/attackers
.size();
1649 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1651 if(!roll_chance_f(chance
))
1654 AddUnitTarget((*aItr
), 1);
1657 // now let next effect cast spell at each target.
1660 case 37877: // Blessing of Faith
1665 uint32 spell_id
= 0;
1666 switch(unitTarget
->getClass())
1668 case CLASS_DRUID
: spell_id
= 37878; break;
1669 case CLASS_PALADIN
: spell_id
= 37879; break;
1670 case CLASS_PRIEST
: spell_id
= 37880; break;
1671 case CLASS_SHAMAN
: spell_id
= 37881; break;
1672 default: return; // ignore for not healing classes
1675 m_caster
->CastSpell(m_caster
,spell_id
,true);
1680 case SPELLFAMILY_SHAMAN
:
1681 //Shaman Rockbiter Weapon
1682 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1684 // TODO: use expect spell for enchant (if exist talent)
1685 // In 3.0.3 no mods present for rockbiter
1686 uint32 spell_id
= 0;
1687 switch(m_spellInfo
->Id
)
1689 case 8017: spell_id
= 36494; break; // Rank 1
1690 case 8018: spell_id
= 36750; break; // Rank 2
1691 case 8019: spell_id
= 36755; break; // Rank 3
1692 case 10399: spell_id
= 36759; break; // Rank 4
1694 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1698 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1702 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1706 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1709 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1711 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1713 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1715 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1717 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1718 // at calculation applied affect from Elemental Weapons talent
1719 // real enchantment damage-1
1720 spell
->m_currentBasePoints
[1] = damage
-1;
1722 SpellCastTargets targets
;
1723 targets
.setItemTarget( item
);
1724 spell
->prepare(&targets
);
1731 if(m_spellInfo
->Id
== 39610) // Mana-Tide Totem effect
1733 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1736 // Regenerate 6% of Total Mana Every 3 secs
1737 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1738 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1742 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1744 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1746 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1749 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1750 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1751 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1753 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1754 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1755 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1757 m_damage
+= m_damage
* damage
/ 100;
1768 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1770 m_caster
->AddPetAura(petSpell
);
1775 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1777 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1780 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1784 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1789 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1792 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1794 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1795 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1799 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1804 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1806 SpellCastTargets targets
;
1807 targets
.setUnitTarget( unitTarget
);
1808 spell
->prepare(&targets
);
1810 m_caster
->SetCurrentCastedSpell(spell
);
1811 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1815 void Spell::EffectForceCast(uint32 i
)
1820 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1823 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1827 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1831 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1834 void Spell::EffectTriggerSpell(uint32 i
)
1836 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1839 switch(triggered_spell_id
)
1844 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1845 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1846 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1848 // if this spell is given to NPC it must handle rest by it's own AI
1849 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1852 // get highest rank of the Stealth spell
1854 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1855 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1857 // only highest rank is shown in spell book, so simply check if shown in spell book
1858 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1861 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1865 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1867 spellId
= spellInfo
->Id
;
1872 // no Stealth spell found
1876 // reset cooldown on it if needed
1877 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1878 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1880 m_caster
->CastSpell(m_caster
, spellId
, true);
1884 case 23770: // Sayge's Dark Fortune of *
1885 // not exist, common cooldown can be implemented in scripts if need.
1887 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1890 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1894 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1895 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1898 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1901 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1905 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1906 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1909 // Righteous Defense
1912 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1918 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1919 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1921 // remove all harmful spells on you...
1922 if( // ignore positive and passive auras
1923 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1924 // ignore physical auras
1925 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1927 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1928 iter
= Auras
.begin();
1933 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1936 if (Unit
*pet
= m_caster
->GetPet())
1937 pet
->CastSpell(pet
, 28305, true);
1943 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1947 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1951 // some triggered spells require specific equipment
1952 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1954 // main hand weapon required
1955 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1957 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1959 // skip spell if no weapon in slot or broken
1960 if(!item
|| item
->IsBroken() )
1963 // skip spell if weapon not fit to triggered spell
1964 if(!item
->IsFitToSpellRequirements(spellInfo
))
1968 // offhand hand weapon required
1969 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1971 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1973 // skip spell if no weapon in slot or broken
1974 if(!item
|| item
->IsBroken() )
1977 // skip spell if weapon not fit to triggered spell
1978 if(!item
->IsFitToSpellRequirements(spellInfo
))
1983 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1984 bool instant
= false;
1985 for(uint32 j
= i
+1; j
< 3; ++j
)
1987 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1997 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
2000 m_TriggerSpells
.push_back(spellInfo
);
2003 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2005 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2008 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2012 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2013 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2018 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2020 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2023 void Spell::EffectTeleportUnits(uint32 i
)
2025 if(!unitTarget
|| unitTarget
->isInFlight())
2028 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2030 case TARGET_INNKEEPER_COORDINATES
:
2032 // Only players can teleport to innkeeper
2033 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2036 ((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);
2039 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2041 // TODO: Only players can teleport?
2042 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2044 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2047 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
2050 ((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);
2053 case TARGET_BEHIND_VICTIM
:
2055 // Get selected target for player (or victim for units)
2056 Unit
*pTarget
= NULL
;
2057 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2058 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2060 pTarget
= m_caster
->getVictim();
2061 // No target present - return
2064 // Init dest coordinates
2065 uint32 mapid
= m_caster
->GetMapId();
2066 float x
= m_targets
.m_destX
;
2067 float y
= m_targets
.m_destY
;
2068 float z
= m_targets
.m_destZ
;
2069 float orientation
= pTarget
->GetOrientation();
2071 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2072 ((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));
2075 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2077 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2078 unitTarget
->SendMessageToSet(&data
, false);
2084 // If not exist data for dest location - return
2085 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2087 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2090 // Init dest coordinates
2091 uint32 mapid
= m_caster
->GetMapId();
2092 float x
= m_targets
.m_destX
;
2093 float y
= m_targets
.m_destY
;
2094 float z
= m_targets
.m_destZ
;
2095 float orientation
= unitTarget
->GetOrientation();
2097 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2098 ((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));
2101 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2103 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2104 unitTarget
->SendMessageToSet(&data
, false);
2110 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2111 switch ( m_spellInfo
->Id
)
2113 // Dimensional Ripper - Everlook
2116 int32 r
= irand(0, 119);
2117 if ( r
>= 70 ) // 7/12 success
2119 if ( r
< 100 ) // 4/12 evil twin
2120 m_caster
->CastSpell(m_caster
,23445,true);
2122 m_caster
->CastSpell(m_caster
,23449,true);
2126 // Ultrasafe Transporter: Toshley's Station
2129 if ( roll_chance_i(50) ) // 50% success
2131 int32 rand_eff
= urand(1,7);
2135 // soul split - evil
2136 m_caster
->CastSpell(m_caster
,36900,true);
2139 // soul split - good
2140 m_caster
->CastSpell(m_caster
,36901,true);
2143 // Increase the size
2144 m_caster
->CastSpell(m_caster
,36895,true);
2147 // Decrease the size
2148 m_caster
->CastSpell(m_caster
,36893,true);
2153 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2154 m_caster
->CastSpell(m_caster
,36897,true);
2156 m_caster
->CastSpell(m_caster
,36899,true);
2161 m_caster
->CastSpell(m_caster
,36940,true);
2165 m_caster
->CastSpell(m_caster
,23445,true);
2171 // Dimensional Ripper - Area 52
2174 if ( roll_chance_i(50) ) // 50% success
2176 int32 rand_eff
= urand(1,4);
2180 // soul split - evil
2181 m_caster
->CastSpell(m_caster
,36900,true);
2184 // soul split - good
2185 m_caster
->CastSpell(m_caster
,36901,true);
2188 // Increase the size
2189 m_caster
->CastSpell(m_caster
,36895,true);
2194 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2195 m_caster
->CastSpell(m_caster
,36897,true);
2197 m_caster
->CastSpell(m_caster
,36899,true);
2207 void Spell::EffectApplyAura(uint32 i
)
2212 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2213 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2214 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2217 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2221 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2223 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2225 // Now Reduce spell duration using data received at spell hit
2226 int32 duration
= Aur
->GetAuraMaxDuration();
2227 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2228 Aur
->setDiminishGroup(m_diminishGroup
);
2230 // if Aura removed and deleted, do not continue.
2231 if(duration
== 0 && !(Aur
->IsPermanent()))
2237 if(duration
!= Aur
->GetAuraMaxDuration())
2239 Aur
->SetAuraMaxDuration(duration
);
2240 Aur
->SetAuraDuration(duration
);
2243 bool added
= unitTarget
->AddAura(Aur
);
2245 // Aura not added and deleted in AddAura call;
2249 // found crash at character loading, broken pointer to Aur...
2250 // Aur was deleted in AddAura()...
2254 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2255 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2256 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2259 void Spell::EffectUnlearnSpecialization( uint32 i
)
2261 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2264 Player
*_player
= (Player
*)unitTarget
;
2265 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2267 _player
->removeSpell(spellToUnlearn
);
2269 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2272 void Spell::EffectPowerDrain(uint32 i
)
2274 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2277 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2281 if(!unitTarget
->isAlive())
2283 if(unitTarget
->getPowerType() != drain_power
)
2288 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2290 //add spell damage bonus
2291 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2293 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2294 uint32 power
= damage
;
2295 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2296 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2299 if(curPower
< power
)
2300 new_damage
= curPower
;
2304 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2306 // Don`t restore from self drain
2307 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2309 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2310 if(manaMultiplier
==0)
2313 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2314 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2316 int32 gain
= int32(new_damage
*manaMultiplier
);
2318 m_caster
->ModifyPower(POWER_MANA
,gain
);
2320 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2324 void Spell::EffectSendEvent(uint32 EffectIndex
)
2326 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2328 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2329 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2331 switch(m_spellInfo
->Id
)
2333 case 23333: // Pickup Horde Flag
2334 /*do not uncomment .
2335 if(bg->GetTypeID()==BATTLEGROUND_WS)
2336 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2337 sLog.outDebug("Send Event Horde Flag Picked Up");
2340 case 23334: // Drop Horde Flag
2341 if(bg->GetTypeID()==BATTLEGROUND_WS)
2342 bg->EventPlayerDroppedFlag((Player*)m_caster);
2343 sLog.outDebug("Drop Horde Flag");
2346 case 23335: // Pickup Alliance Flag
2347 /*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
2348 if(bg->GetTypeID()==BATTLEGROUND_WS)
2349 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2350 sLog.outDebug("Send Event Alliance Flag Picked Up");
2353 case 23336: // Drop Alliance Flag
2354 if(bg->GetTypeID()==BATTLEGROUND_WS)
2355 bg->EventPlayerDroppedFlag((Player*)m_caster);
2356 sLog.outDebug("Drop Alliance Flag");
2358 case 23385: // Alliance Flag Returns
2359 if(bg->GetTypeID()==BATTLEGROUND_WS)
2360 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2361 sLog.outDebug("Alliance Flag Returned");
2363 case 23386: // Horde Flag Returns
2364 if(bg->GetTypeID()==BATTLEGROUND_WS)
2365 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2366 sLog.outDebug("Horde Flag Returned");
2370 if(bg->GetTypeID()==BATTLEGROUND_EY)
2371 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2375 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2380 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2381 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2384 void Spell::EffectPowerBurn(uint32 i
)
2386 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2389 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2393 if(!unitTarget
->isAlive())
2395 if(unitTarget
->getPowerType()!=powertype
)
2400 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2402 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2403 uint32 power
= damage
;
2404 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2405 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2407 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2409 unitTarget
->ModifyPower(powertype
,-new_damage
);
2410 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2412 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2413 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2415 new_damage
= int32(new_damage
*multiplier
);
2416 m_damage
+=new_damage
;
2419 void Spell::EffectHeal( uint32
/*i*/ )
2421 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2423 // Try to get original caster
2424 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2426 // Skip if m_originalCaster not available
2430 int32 addhealth
= damage
;
2432 // Vessel of the Naaru (Vial of the Sunwell trinket)
2433 if (m_spellInfo
->Id
== 45064)
2435 // Amount of heal - depends from stacked Holy Energy
2436 int damageAmount
= 0;
2437 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2438 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2439 if((*i
)->GetId() == 45062)
2440 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2442 m_caster
->RemoveAurasDueToSpell(45062);
2444 addhealth
+= damageAmount
;
2446 // Swiftmend - consumes Regrowth or Rejuvenation
2447 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2449 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2450 // find most short by duration
2451 Aura
*targetAura
= NULL
;
2452 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2454 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2455 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2457 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2464 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2470 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2475 int32 tickheal
= caster
->SpellHealingBonus(targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
, unitTarget
);
2476 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2477 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2479 addhealth
+= tickheal
* tickcount
;
2482 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, addhealth
,HEAL
, unitTarget
);
2484 m_healing
+=addhealth
;
2488 void Spell::EffectHealPct( uint32
/*i*/ )
2490 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2492 // Try to get original caster
2493 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2495 // Skip if m_originalCaster not available
2499 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2500 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2502 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2503 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2505 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2506 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2507 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2511 void Spell::EffectHealMechanical( uint32
/*i*/ )
2513 // Mechanic creature type should be correctly checked by targetCreatureType field
2514 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2516 // Try to get original caster
2517 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2519 // Skip if m_originalCaster not available
2523 uint32 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, uint32(damage
), HEAL
, unitTarget
);
2524 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2525 unitTarget
->ModifyHealth( int32(damage
) );
2529 void Spell::EffectHealthLeech(uint32 i
)
2533 if(!unitTarget
->isAlive())
2539 sLog
.outDebug("HealthLeech :%i", damage
);
2541 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2543 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2544 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2546 int32 new_damage
= int32(damage
*multiplier
);
2547 uint32 curHealth
= unitTarget
->GetHealth();
2548 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2549 if(curHealth
< new_damage
)
2550 new_damage
= curHealth
;
2552 if(m_caster
->isAlive())
2554 new_damage
= m_caster
->SpellHealingBonus(m_spellInfo
, new_damage
, HEAL
, m_caster
);
2556 m_caster
->ModifyHealth(new_damage
);
2558 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2559 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2561 // m_healthLeech+=tmpvalue;
2562 // m_damage+=new_damage;
2565 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2567 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2570 Player
* player
= (Player
*)unitTarget
;
2572 uint32 newitemid
= itemtype
;
2573 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2576 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2582 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2583 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2585 int32 basePoints
= m_currentBasePoints
[i
];
2586 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2588 num_to_add
= basePoints
+ irand(1, randomPoints
);
2590 num_to_add
= basePoints
+ 1;
2592 else if (pProto
->MaxCount
== 1)
2594 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2596 int32 basePoints
= m_currentBasePoints
[i
];
2597 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2598 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2605 if (num_to_add
> pProto
->GetMaxStackSize())
2606 num_to_add
= pProto
->GetMaxStackSize();
2608 // init items_count to 1, since 1 item will be created regardless of specialization
2610 // the chance to create additional items
2611 float additionalCreateChance
=0.0f
;
2612 // the maximum number of created additional items
2613 uint8 additionalMaxNum
=0;
2614 // get the chance and maximum number for creating extra items
2615 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2617 // roll with this chance till we roll not to create or we create the max num
2618 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2622 // really will be created more items
2623 num_to_add
*= items_count
;
2625 // can the player store the new item?
2626 ItemPosCountVec dest
;
2627 uint32 no_space
= 0;
2628 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2629 if( msg
!= EQUIP_ERR_OK
)
2631 // convert to possible store amount
2632 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2633 num_to_add
-= no_space
;
2636 // if not created by another reason from full inventory or unique items amount limitation
2637 player
->SendEquipError( msg
, NULL
, NULL
);
2644 // create the new item and store it
2645 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2647 // was it successful? return error if not
2650 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2654 // set the "Crafted by ..." property of the item
2655 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2656 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2658 // send info to the client
2660 player
->SendNewItem(pItem
, num_to_add
, true, true);
2662 // we succeeded in creating at least one item, so a levelup is possible
2663 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2666 // for battleground marks send by mail if not add all expected
2669 BattleGroundTypeId bgType
;
2670 switch(m_spellInfo
->Id
)
2672 case SPELL_AV_MARK_WINNER
:
2673 case SPELL_AV_MARK_LOSER
:
2674 bgType
= BATTLEGROUND_AV
;
2676 case SPELL_WS_MARK_WINNER
:
2677 case SPELL_WS_MARK_LOSER
:
2678 bgType
= BATTLEGROUND_WS
;
2680 case SPELL_AB_MARK_WINNER
:
2681 case SPELL_AB_MARK_LOSER
:
2682 bgType
= BATTLEGROUND_AB
;
2688 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2689 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2693 void Spell::EffectCreateItem(uint32 i
)
2695 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2698 void Spell::EffectPersistentAA(uint32 i
)
2700 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2702 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2703 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2705 int32 duration
= GetSpellDuration(m_spellInfo
);
2706 DynamicObject
* dynObj
= new DynamicObject
;
2707 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
))
2712 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2713 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2714 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2715 m_caster
->AddDynObject(dynObj
);
2716 dynObj
->GetMap()->Add(dynObj
);
2719 void Spell::EffectEnergize(uint32 i
)
2723 if(!unitTarget
->isAlive())
2726 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2729 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2731 // Some level depends spells
2734 switch (m_spellInfo
->Id
)
2738 level_diff
= m_caster
->getLevel() - 40;
2743 level_diff
= m_caster
->getLevel() - 60;
2748 level_diff
= m_caster
->getLevel() - 60;
2756 damage
-= multiplier
* level_diff
;
2761 if(unitTarget
->GetMaxPower(power
) == 0)
2764 unitTarget
->ModifyPower(power
,damage
);
2765 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2767 // Mad Alchemist's Potion
2768 if (m_spellInfo
->Id
== 45051)
2770 // find elixirs on target
2771 uint32 elixir_mask
= 0;
2772 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2773 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2775 uint32 spell_id
= itr
->second
->GetId();
2776 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2777 elixir_mask
|= mask
;
2780 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2781 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2783 // get all available elixirs by mask and spell level
2784 std::vector
<uint32
> elixirs
;
2785 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2786 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2788 if (itr
->second
& elixir_mask
)
2790 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2793 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2794 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2797 elixirs
.push_back(itr
->first
);
2801 if (!elixirs
.empty())
2803 // cast random elixir on target
2804 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2805 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2810 void Spell::EffectEnergisePct(uint32 i
)
2814 if(!unitTarget
->isAlive())
2817 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2820 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2822 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2826 uint32 gain
= damage
* maxPower
/ 100;
2827 unitTarget
->ModifyPower(power
, gain
);
2828 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2831 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2833 Player
* player
= (Player
*)m_caster
;
2839 if (Script
->GOHello(player
, gameObjTarget
))
2842 switch (gameObjTarget
->GetGoType())
2844 case GAMEOBJECT_TYPE_DOOR
:
2845 case GAMEOBJECT_TYPE_BUTTON
:
2846 gameObjTarget
->UseDoorOrButton();
2847 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2850 case GAMEOBJECT_TYPE_QUESTGIVER
:
2851 // start or end quest
2852 player
->PrepareQuestMenu(guid
);
2853 player
->SendPreparedQuest(guid
);
2856 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2857 // triggering linked GO
2858 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2859 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2862 case GAMEOBJECT_TYPE_GOOBER
:
2863 // goober_scripts can be triggered if the player don't have the quest
2864 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2866 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2867 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2870 // cast goober spell
2871 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2872 ///Quest require to be active for GO using
2873 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2876 gameObjTarget
->AddUniqueUse(player
);
2877 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2879 //TODO? Objective counting called without spell check but with quest objective check
2880 // if send spell id then this line will duplicate to spell casting call (double counting)
2881 // So we or have this line and not required in quest_template have reqSpellIdN
2882 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2883 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2885 // triggering linked GO
2886 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2887 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2891 case GAMEOBJECT_TYPE_CHEST
:
2892 // TODO: possible must be moved to loot release (in different from linked triggering)
2893 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2895 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2896 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2899 // triggering linked GO
2900 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2901 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2903 // Don't return, let loots been taken
2908 player
->SendLoot(guid
, loottype
);
2911 void Spell::EffectOpenLock(uint32
/*i*/)
2913 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2915 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2919 Player
* player
= (Player
*)m_caster
;
2921 LootType loottype
= LOOT_CORPSE
;
2928 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2929 // Arathi Basin banner opening !
2930 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2931 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2933 //isAllowUseBattleGroundObject() already called in CanCast()
2934 // in battleground check
2935 if(BattleGround
*bg
= player
->GetBattleGround())
2937 // check if it's correct bg
2938 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2939 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2943 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2945 //isAllowUseBattleGroundObject() already called in CanCast()
2946 // in battleground check
2947 if(BattleGround
*bg
= player
->GetBattleGround())
2949 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2950 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2954 lockId
= gameObjTarget
->GetLockId();
2955 guid
= gameObjTarget
->GetGUID();
2959 lockId
= itemTarget
->GetProto()->LockID
;
2960 guid
= itemTarget
->GetGUID();
2964 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2968 if(!lockId
) // possible case for GO and maybe for items.
2970 SendLoot(guid
, loottype
);
2975 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2979 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2980 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2981 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2986 for(int i
= 0; i
< 8; ++i
)
2988 // Type==1 This means lockInfo->Index[i] is an item
2989 if(lockInfo
->Type
[i
]==LOCK_KEY_ITEM
&& lockInfo
->Index
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->Index
[i
])
2991 SendLoot(guid
, loottype
);
2997 // Check and skill-up skill
2998 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
2999 SkillId
= m_spellInfo
->EffectMiscValue
[1];
3000 // pickpocketing spells
3001 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
3002 SkillId
= SKILL_LOCKPICKING
;
3004 // skill bonus provided by casting spell (mostly item spells)
3005 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
3007 uint32 reqSkillValue
= lockInfo
->Skill
[0];
3009 if(lockInfo
->Skill
[1]) // required pick lock skill applying
3011 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
3013 SendCastResult(SPELL_FAILED_FIZZLE
);
3017 reqSkillValue
= lockInfo
->Skill
[1];
3019 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
3021 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
3027 loottype
= LOOT_SKINNING
;
3028 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
3030 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
3034 // update skill if really known
3035 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3036 if(SkillValue
) // non only item base skill
3040 // Allow one skill-up until respawned
3041 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3042 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
3043 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3048 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3049 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
3054 SendLoot(guid
, loottype
);
3057 void Spell::EffectSummonChangeItem(uint32 i
)
3059 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3062 Player
*player
= (Player
*)m_caster
;
3064 // applied only to using item
3068 // ... only to item in own inventory/bank/equip_slot
3069 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3072 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3076 uint16 pos
= m_CastItem
->GetPos();
3078 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3082 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3084 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3085 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3088 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3090 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3091 player
->DurabilityLoss(pNewItem
, loosePercent
);
3094 if( player
->IsInventoryPos( pos
) )
3096 ItemPosCountVec dest
;
3097 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3098 if( msg
== EQUIP_ERR_OK
)
3100 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3102 // prevent crash at access and unexpected charges counting with item update queue corrupt
3103 if(m_CastItem
==m_targets
.getItemTarget())
3104 m_targets
.setItemTarget(NULL
);
3108 player
->StoreItem( dest
, pNewItem
, true);
3112 else if( player
->IsBankPos ( pos
) )
3114 ItemPosCountVec dest
;
3115 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3116 if( msg
== EQUIP_ERR_OK
)
3118 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3120 // prevent crash at access and unexpected charges counting with item update queue corrupt
3121 if(m_CastItem
==m_targets
.getItemTarget())
3122 m_targets
.setItemTarget(NULL
);
3126 player
->BankItem( dest
, pNewItem
, true);
3130 else if( player
->IsEquipmentPos ( pos
) )
3133 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3134 if( msg
== EQUIP_ERR_OK
)
3136 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3138 // prevent crash at access and unexpected charges counting with item update queue corrupt
3139 if(m_CastItem
==m_targets
.getItemTarget())
3140 m_targets
.setItemTarget(NULL
);
3144 player
->EquipItem( dest
, pNewItem
, true);
3145 player
->AutoUnequipOffhandIfNeed();
3154 void Spell::EffectOpenSecretSafe(uint32 i
)
3156 EffectOpenLock(i
); //no difference for now
3159 void Spell::EffectProficiency(uint32
/*i*/)
3161 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3163 Player
*p_target
= (Player
*)unitTarget
;
3165 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3166 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3168 p_target
->AddWeaponProficiency(subClassMask
);
3169 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3171 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3173 p_target
->AddArmorProficiency(subClassMask
);
3174 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3178 void Spell::EffectApplyAreaAura(uint32 i
)
3182 if(!unitTarget
->isAlive())
3185 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3186 unitTarget
->AddAura(Aur
);
3189 void Spell::EffectSummonType(uint32 i
)
3191 switch(m_spellInfo
->EffectMiscValueB
[i
])
3193 case SUMMON_TYPE_GUARDIAN
:
3194 case SUMMON_TYPE_POSESSED
:
3195 case SUMMON_TYPE_POSESSED2
:
3196 case SUMMON_TYPE_FORCE_OF_NATURE
:
3197 case SUMMON_TYPE_GUARDIAN2
:
3198 EffectSummonGuardian(i
);
3200 case SUMMON_TYPE_WILD
:
3201 EffectSummonWild(i
);
3203 case SUMMON_TYPE_DEMON
:
3204 EffectSummonDemon(i
);
3206 case SUMMON_TYPE_SUMMON
:
3209 case SUMMON_TYPE_CRITTER
:
3210 case SUMMON_TYPE_CRITTER2
:
3211 case SUMMON_TYPE_CRITTER3
:
3212 EffectSummonCritter(i
);
3214 case SUMMON_TYPE_TOTEM_SLOT1
:
3215 case SUMMON_TYPE_TOTEM_SLOT2
:
3216 case SUMMON_TYPE_TOTEM_SLOT3
:
3217 case SUMMON_TYPE_TOTEM_SLOT4
:
3218 case SUMMON_TYPE_TOTEM
:
3219 EffectSummonTotem(i
);
3221 case SUMMON_TYPE_UNKNOWN1
:
3222 case SUMMON_TYPE_UNKNOWN2
:
3223 case SUMMON_TYPE_UNKNOWN3
:
3224 case SUMMON_TYPE_UNKNOWN4
:
3225 case SUMMON_TYPE_UNKNOWN5
:
3228 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3233 void Spell::EffectSummon(uint32 i
)
3235 if(m_caster
->GetPetGUID())
3240 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3243 uint32 level
= m_caster
->getLevel();
3244 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3246 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3248 // set timer for unsummon
3249 int32 duration
= GetSpellDuration(m_spellInfo
);
3251 spawnCreature
->SetDuration(duration
);
3256 Map
*map
= m_caster
->GetMap();
3257 uint32 pet_number
= objmgr
.GeneratePetNumber();
3258 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3260 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3261 delete spawnCreature
;
3265 // Summon in dest location
3267 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3269 x
= m_targets
.m_destX
;
3270 y
= m_targets
.m_destY
;
3271 z
= m_targets
.m_destZ
;
3274 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3276 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3278 if(!spawnCreature
->IsPositionValid())
3280 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3281 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3282 delete spawnCreature
;
3286 // set timer for unsummon
3287 int32 duration
= GetSpellDuration(m_spellInfo
);
3289 spawnCreature
->SetDuration(duration
);
3291 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3292 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3293 spawnCreature
->setPowerType(POWER_MANA
);
3294 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3295 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3296 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3297 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3298 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3299 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3300 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3301 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3302 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3304 spawnCreature
->InitStatsForLevel(level
);
3306 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3308 spawnCreature
->AIM_Initialize();
3309 spawnCreature
->InitPetCreateSpells();
3310 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3311 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3313 std::string name
= m_caster
->GetName();
3314 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3315 spawnCreature
->SetName( name
);
3317 map
->Add((Creature
*)spawnCreature
);
3319 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3321 m_caster
->SetPet(spawnCreature
);
3322 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3323 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3324 ((Player
*)m_caster
)->PetSpellInitialize();
3328 void Spell::EffectLearnSpell(uint32 i
)
3333 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3335 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3336 EffectLearnPetSpell(i
);
3341 Player
*player
= (Player
*)unitTarget
;
3343 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3344 player
->learnSpell(spellToLearn
,false);
3346 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3349 void Spell::EffectDispel(uint32 i
)
3354 // Fill possible dispell list
3355 std::vector
<Aura
*> dispel_list
;
3357 // Create dispel mask by dispel type
3358 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3359 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3360 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3361 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3363 Aura
*aur
= (*itr
).second
;
3364 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3366 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3368 bool positive
= true;
3369 if (!aur
->IsPositive())
3372 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3374 // do not remove positive auras if friendly target
3375 // negative auras if non-friendly target
3376 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3379 // Add aura to dispel list
3380 dispel_list
.push_back(aur
);
3383 // Ok if exist some buffs for dispel try dispel it
3384 if (!dispel_list
.empty())
3386 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3387 std::list
< uint32
> fail_list
; // spell_id
3388 int32 list_size
= dispel_list
.size();
3389 // Dispell N = damage buffs (or while exist buffs for dispel)
3390 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3392 // Random select buff for dispel
3393 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3395 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3396 // Base dispel chance
3397 // TODO: possible chance depend from spell level??
3398 int32 miss_chance
= 0;
3399 // Apply dispel mod from aura caster
3400 if (Unit
*caster
= aur
->GetCaster())
3402 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3403 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3406 if (roll_chance_i(miss_chance
))
3407 fail_list
.push_back(aur
->GetId());
3409 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3410 // Remove buff from list for prevent doubles
3411 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3413 Aura
*dispeled
= *j
;
3414 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3416 j
= dispel_list
.erase(j
);
3423 // Send success log and really remove auras
3424 if (!success_list
.empty())
3426 int32 count
= success_list
.size();
3427 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3428 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3429 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3430 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3431 data
<< uint8(0); // not used
3432 data
<< uint32(count
); // count
3433 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3435 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3436 data
<< uint32(spellInfo
->Id
); // Spell Id
3437 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3438 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3440 m_caster
->SendMessageToSet(&data
, true);
3444 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3446 uint32 heal_spell
= 0;
3447 switch (m_spellInfo
->Id
)
3449 case 19505: heal_spell
= 19658; break;
3450 case 19731: heal_spell
= 19732; break;
3451 case 19734: heal_spell
= 19733; break;
3452 case 19736: heal_spell
= 19735; break;
3453 case 27276: heal_spell
= 27278; break;
3454 case 27277: heal_spell
= 27279; break;
3456 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3460 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3463 // Send fail log to client
3464 if (!fail_list
.empty())
3466 // Failed to dispell
3467 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3468 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3469 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3470 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3471 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3472 data
<< uint32(*j
); // Spell Id
3473 m_caster
->SendMessageToSet(&data
, true);
3478 void Spell::EffectDualWield(uint32
/*i*/)
3480 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3481 ((Player
*)unitTarget
)->SetCanDualWield(true);
3484 void Spell::EffectPull(uint32
/*i*/)
3486 // TODO: create a proper pull towards distract spell center for distract
3487 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3490 void Spell::EffectDistract(uint32
/*i*/)
3492 // Check for possible target
3493 if (!unitTarget
|| unitTarget
->isInCombat())
3496 // target must be OK to do this
3497 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3500 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3502 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3504 // For players just turn them
3506 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3507 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3508 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3512 // Set creature Distracted, Stop it, And turn it
3513 unitTarget
->SetOrientation(angle
);
3514 unitTarget
->StopMoving();
3515 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3519 void Spell::EffectPickPocket(uint32
/*i*/)
3521 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3524 // victim must be creature and attackable
3525 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3528 // victim have to be alive and humanoid or undead
3529 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3531 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3533 if (chance
> irand(0, 19))
3535 // Stealing successful
3536 //sLog.outDebug("Sending loot from pickpocket");
3537 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3541 // Reveal action + get attack
3542 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3543 if (((Creature
*)unitTarget
)->AI())
3544 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3549 void Spell::EffectAddFarsight(uint32 i
)
3551 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3552 int32 duration
= GetSpellDuration(m_spellInfo
);
3553 DynamicObject
* dynObj
= new DynamicObject
;
3554 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
))
3559 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3560 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3561 m_caster
->AddDynObject(dynObj
);
3562 dynObj
->GetMap()->Add(dynObj
);
3563 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3564 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3567 void Spell::EffectSummonWild(uint32 i
)
3569 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3573 uint32 level
= m_caster
->getLevel();
3575 // level of creature summoned using engineering item based at engineering skill level
3576 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3578 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3579 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3581 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3589 // select center of summon position
3590 float center_x
= m_targets
.m_destX
;
3591 float center_y
= m_targets
.m_destY
;
3592 float center_z
= m_targets
.m_destZ
;
3594 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3596 int32 amount
= damage
> 0 ? damage
: 1;
3598 for(int32 count
= 0; count
< amount
; ++count
)
3601 // If dest location if present
3602 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3604 // Summon 1 unit in dest location
3607 px
= m_targets
.m_destX
;
3608 py
= m_targets
.m_destY
;
3609 pz
= m_targets
.m_destZ
;
3611 // Summon in random point all other units if location present
3613 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3615 // Summon if dest location not present near caster
3617 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3619 int32 duration
= GetSpellDuration(m_spellInfo
);
3621 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3623 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3627 void Spell::EffectSummonGuardian(uint32 i
)
3629 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3633 // Jewelery statue case (totem like)
3634 if(m_spellInfo
->SpellIconID
==2056)
3636 EffectSummonTotem(i
);
3640 // set timer for unsummon
3641 int32 duration
= GetSpellDuration(m_spellInfo
);
3643 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3644 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3645 // so this code hack in fact
3646 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3647 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3648 return; // find old guardian, ignore summon
3650 // in another case summon new
3651 uint32 level
= m_caster
->getLevel();
3653 // level of pet summoned using engineering item based at engineering skill level
3654 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3656 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3657 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3659 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3667 // select center of summon position
3668 float center_x
= m_targets
.m_destX
;
3669 float center_y
= m_targets
.m_destY
;
3670 float center_z
= m_targets
.m_destZ
;
3672 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3674 int32 amount
= damage
> 0 ? damage
: 1;
3676 for(int32 count
= 0; count
< amount
; ++count
)
3678 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3680 Map
*map
= m_caster
->GetMap();
3681 uint32 pet_number
= objmgr
.GeneratePetNumber();
3682 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3684 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3685 delete spawnCreature
;
3690 // If dest location if present
3691 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3693 // Summon 1 unit in dest location
3696 px
= m_targets
.m_destX
;
3697 py
= m_targets
.m_destY
;
3698 pz
= m_targets
.m_destZ
;
3700 // Summon in random point all other units if location present
3702 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3704 // Summon if dest location not present near caster
3706 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3708 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3710 if(!spawnCreature
->IsPositionValid())
3712 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3713 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3714 delete spawnCreature
;
3719 spawnCreature
->SetDuration(duration
);
3721 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3722 spawnCreature
->setPowerType(POWER_MANA
);
3723 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3724 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3725 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3726 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3727 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3728 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3729 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3731 spawnCreature
->InitStatsForLevel(level
);
3732 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3734 spawnCreature
->AIM_Initialize();
3736 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3737 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3739 map
->Add((Creature
*)spawnCreature
);
3743 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3748 if(unitTarget
->isInFlight())
3751 uint32 mapid
= m_caster
->GetMapId();
3752 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3755 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3757 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3758 ((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));
3760 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3763 void Spell::EffectLearnSkill(uint32 i
)
3765 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3771 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3772 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3773 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3776 void Spell::EffectAddHonor(uint32
/*i*/)
3778 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3781 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3783 // TODO: find formula for honor reward based on player's level!
3785 // now fixed only for level 70 players:
3786 if (((Player
*)unitTarget
)->getLevel() == 70)
3787 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3790 void Spell::EffectTradeSkill(uint32
/*i*/)
3792 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3794 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3795 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3796 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3799 void Spell::EffectEnchantItemPerm(uint32 i
)
3801 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3806 Player
* p_caster
= (Player
*)m_caster
;
3808 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3810 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3814 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3818 // item can be in trade slot and have owner diff. from caster
3819 Player
* item_owner
= itemTarget
->GetOwner();
3823 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3825 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3826 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3827 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3828 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3831 // remove old enchanting before applying new if equipped
3832 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3834 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3836 // add new enchanting if equipped
3837 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3840 void Spell::EffectEnchantItemTmp(uint32 i
)
3842 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3845 Player
* p_caster
= (Player
*)m_caster
;
3850 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3852 // Shaman Rockbiter Weapon
3853 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3855 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3857 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3858 // with already applied percent bonus from Elemental Weapons talent
3859 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3860 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3861 switch(enchnting_damage
)
3864 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3866 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3867 case 5: enchant_id
= 3025; break; // 20%
3869 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3870 case 7: enchant_id
= 3027; break; // 20%
3872 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3873 case 10: enchant_id
= 503; break; // 14%
3874 case 11: enchant_id
= 3031; break; // 20%
3876 case 15: enchant_id
= 3035; break; // 0%
3877 case 16: enchant_id
= 1663; break; // 7%
3878 case 17: enchant_id
= 3033; break; // 14%
3879 case 18: enchant_id
= 3034; break; // 20%
3881 case 28: enchant_id
= 3038; break; // 0%
3882 case 29: enchant_id
= 683; break; // 7%
3883 case 31: enchant_id
= 3036; break; // 14%
3884 case 33: enchant_id
= 3037; break; // 20%
3886 case 40: enchant_id
= 3041; break; // 0%
3887 case 42: enchant_id
= 1664; break; // 7%
3888 case 45: enchant_id
= 3039; break; // 14%
3889 case 48: enchant_id
= 3040; break; // 20%
3891 case 49: enchant_id
= 3044; break; // 0%
3892 case 52: enchant_id
= 2632; break; // 7%
3893 case 55: enchant_id
= 3042; break; // 14%
3894 case 58: enchant_id
= 3043; break; // 20%
3896 case 62: enchant_id
= 2633; break; // 0%
3897 case 66: enchant_id
= 3018; break; // 7%
3898 case 70: enchant_id
= 3019; break; // 14%
3899 case 74: enchant_id
= 3020; break; // 20%
3901 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3908 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3912 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3915 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3919 // select enchantment duration
3922 // rogue family enchantments exception by duration
3923 if(m_spellInfo
->Id
==38615)
3924 duration
= 1800; // 30 mins
3925 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3926 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3927 duration
= 3600; // 1 hour
3928 // shaman family enchantments
3929 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3930 duration
= 1800; // 30 mins
3931 // other cases with this SpellVisual already selected
3932 else if(m_spellInfo
->SpellVisual
[0]==215)
3933 duration
= 1800; // 30 mins
3934 // some fishing pole bonuses
3935 else if(m_spellInfo
->SpellVisual
[0]==563)
3936 duration
= 600; // 10 mins
3937 // shaman rockbiter enchantments
3938 else if(m_spellInfo
->SpellVisual
[0]==0)
3939 duration
= 1800; // 30 mins
3940 else if(m_spellInfo
->Id
==29702)
3941 duration
= 300; // 5 mins
3942 else if(m_spellInfo
->Id
==37360)
3943 duration
= 300; // 5 mins
3946 duration
= 3600; // 1 hour
3948 // item can be in trade slot and have owner diff. from caster
3949 Player
* item_owner
= itemTarget
->GetOwner();
3953 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3955 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3956 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3957 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3958 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3961 // remove old enchanting before applying new if equipped
3962 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3964 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3966 // add new enchanting if equipped
3967 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3970 void Spell::EffectTameCreature(uint32
/*i*/)
3972 if(m_caster
->GetPetGUID())
3978 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3981 Creature
* creatureTarget
= (Creature
*)unitTarget
;
3983 if(creatureTarget
->isPet())
3986 if(m_caster
->getClass() != CLASS_HUNTER
)
3989 // cast finish successfully
3990 //SendChannelUpdate(0);
3993 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
3995 // kill original creature
3996 creatureTarget
->setDeathState(JUST_DIED
);
3997 creatureTarget
->RemoveCorpse();
3998 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4000 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4002 // prepare visual effect for levelup
4003 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4006 pet
->GetMap()->Add((Creature
*)pet
);
4008 // visual effect for levelup
4009 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4011 // caster have pet now
4012 m_caster
->SetPet(pet
);
4014 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4016 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4017 ((Player
*)m_caster
)->PetSpellInitialize();
4021 void Spell::EffectSummonPet(uint32 i
)
4023 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4025 Pet
*OldSummon
= m_caster
->GetPet();
4027 // if pet requested type already exist
4030 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4032 // pet in corpse state can't be summoned
4033 if( OldSummon
->isDead() )
4036 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4037 OldSummon
->SetMapId(m_caster
->GetMapId());
4040 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4042 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4043 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4045 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4047 ((Player
*)m_caster
)->PetSpellInitialize();
4052 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4053 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4058 Pet
* NewSummon
= new Pet
;
4060 // petentry==0 for hunter "call pet" (current pet summoned if any)
4061 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4063 if(NewSummon
->getPetType()==SUMMON_PET
)
4065 // Remove Demonic Sacrifice auras (known pet)
4066 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4067 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4069 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4071 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4072 itr
= auraClassScripts
.begin();
4082 // not error in case fail hunter call pet
4089 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4093 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4098 Map
*map
= m_caster
->GetMap();
4099 uint32 pet_number
= objmgr
.GeneratePetNumber();
4100 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, petentry
, pet_number
))
4107 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4109 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4111 if(!NewSummon
->IsPositionValid())
4113 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4114 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4119 uint32 petlevel
= m_caster
->getLevel();
4120 NewSummon
->setPetType(SUMMON_PET
);
4122 uint32 faction
= m_caster
->getFaction();
4123 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4125 if ( ((Creature
*)m_caster
)->isTotem() )
4126 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4128 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4131 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4132 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4133 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4134 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4135 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4136 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4137 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4138 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4139 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4140 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4142 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4143 // this enables pet details window (Shift+P)
4145 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4146 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4147 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4149 NewSummon
->InitStatsForLevel(petlevel
);
4150 NewSummon
->InitPetCreateSpells();
4151 NewSummon
->InitTalentForLevel();
4153 if(NewSummon
->getPetType()==SUMMON_PET
)
4155 // Remove Demonic Sacrifice auras (new pet)
4156 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4157 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4159 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4161 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4162 itr
= auraClassScripts
.begin();
4168 // generate new name for summon pet
4169 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4170 if(!new_name
.empty())
4171 NewSummon
->SetName(new_name
);
4173 else if(NewSummon
->getPetType()==HUNTER_PET
)
4174 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4176 NewSummon
->AIM_Initialize();
4177 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4178 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4180 map
->Add((Creature
*)NewSummon
);
4182 m_caster
->SetPet(NewSummon
);
4183 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4185 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4187 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4188 ((Player
*)m_caster
)->PetSpellInitialize();
4192 void Spell::EffectLearnPetSpell(uint32 i
)
4194 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4197 Player
*_player
= (Player
*)m_caster
;
4199 Pet
*pet
= _player
->GetPet();
4205 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4206 if(!learn_spellproto
)
4209 pet
->learnSpell(learn_spellproto
->Id
);
4211 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4212 _player
->PetSpellInitialize();
4215 void Spell::EffectTaunt(uint32
/*i*/)
4217 // this effect use before aura Taunt apply for prevent taunt already attacking target
4218 // for spell as marked "non effective at already attacking target"
4219 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4221 if(unitTarget
->getVictim()==m_caster
)
4223 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4228 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4229 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4230 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4233 void Spell::EffectWeaponDmg(uint32 i
)
4237 if(!unitTarget
->isAlive())
4240 // multiple weapon dmg effect workaround
4241 // execute only the last weapon damage
4242 // and handle all effects at once
4243 for (int j
= 0; j
< 3; j
++)
4245 switch(m_spellInfo
->Effect
[j
])
4247 case SPELL_EFFECT_WEAPON_DAMAGE
:
4248 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4249 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4250 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4251 if (j
< i
) // we must calculate only at last weapon effect
4257 // some spell specific modifiers
4258 bool customBonusDamagePercentMod
= false;
4259 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4260 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4261 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4262 bool normalized
= false;
4264 int32 spell_bonus
= 0; // bonus specific for spell
4265 switch(m_spellInfo
->SpellFamilyName
)
4267 case SPELLFAMILY_WARRIOR
:
4269 // Whirlwind, single only spell with 2 weapon white damage apply if have
4270 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4272 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4273 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4275 // Devastate bonus and sunder armor refresh
4276 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4279 // Need refresh all Sunder Armor auras from this caster
4280 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4281 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4283 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4284 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4285 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4286 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4288 (*itr
).second
->RefreshAura();
4289 stack
= (*itr
).second
->GetStackAmount();
4293 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4297 case SPELLFAMILY_ROGUE
:
4300 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4302 customBonusDamagePercentMod
= true;
4303 bonusDamagePercentMod
= 2.5f
; // 250%
4305 // Mutilate (for each hand)
4306 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4310 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4315 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4316 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4318 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4327 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4331 case SPELLFAMILY_PALADIN
:
4333 // Seal of Command - receive benefit from Spell Damage and Healing
4334 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4336 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4337 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4341 case SPELLFAMILY_SHAMAN
:
4343 // Skyshatter Harness item set bonus
4345 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4347 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4348 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4350 // Stormstrike AP Buff
4351 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4353 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4361 int32 fixed_bonus
= 0;
4362 for (int j
= 0; j
< 3; j
++)
4364 switch(m_spellInfo
->Effect
[j
])
4366 case SPELL_EFFECT_WEAPON_DAMAGE
:
4367 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4368 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4370 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4371 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4374 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4375 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4377 // applied only to prev.effects fixed damage
4378 if(customBonusDamagePercentMod
)
4379 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4381 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4384 break; // not weapon damage effect, just skip
4388 // non-weapon damage
4389 int32 bonus
= spell_bonus
+ fixed_bonus
;
4391 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4395 switch(m_attackType
)
4398 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4399 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4400 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4403 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4404 bonus
= int32(bonus
*weapon_total_pct
);
4407 // + weapon damage with applied weapon% dmg to base weapon damage in call
4408 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4411 bonus
= int32(bonus
*totalDamagePercentMod
);
4413 // prevent negative damage
4414 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4416 // Add melee damage bonuses (also check for negative)
4417 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4418 m_damage
+= eff_damage
;
4421 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4423 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4424 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4428 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4430 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4431 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4435 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4437 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4439 // wands don't have ammo
4440 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4443 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4445 if(pItem
->GetMaxStackCount()==1)
4447 // decrease durability for non-stackable throw weapon
4448 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4452 // decrease items amount for stackable throw weapon
4454 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4457 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4458 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4462 void Spell::EffectThreat(uint32
/*i*/)
4464 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4467 if(!unitTarget
->CanHaveThreatList())
4470 unitTarget
->AddThreat(m_caster
, float(damage
));
4473 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4477 if(!unitTarget
->isAlive())
4480 uint32 heal
= m_caster
->GetMaxHealth();
4485 void Spell::EffectInterruptCast(uint32
/*i*/)
4489 if(!unitTarget
->isAlive())
4492 // TODO: not all spells that used this effect apply cooldown at school spells
4493 // also exist case: apply cooldown to interrupted cast only and to all spells
4494 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4496 if (unitTarget
->m_currentSpells
[i
])
4498 // check if we can interrupt spell
4499 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4501 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4502 unitTarget
->InterruptSpell(i
,false);
4508 void Spell::EffectSummonObjectWild(uint32 i
)
4510 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4512 GameObject
* pGameObj
= new GameObject
;
4514 WorldObject
* target
= focusObject
;
4519 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4521 x
= m_targets
.m_destX
;
4522 y
= m_targets
.m_destY
;
4523 z
= m_targets
.m_destZ
;
4526 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4528 Map
*map
= target
->GetMap();
4530 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4531 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4537 int32 duration
= GetSpellDuration(m_spellInfo
);
4538 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4539 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4541 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4542 m_caster
->AddGameObject(pGameObj
);
4545 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4547 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4549 Player
*pl
= (Player
*)m_caster
;
4550 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4551 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4553 uint32 team
= ALLIANCE
;
4555 if(pl
->GetTeam() == team
)
4558 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4563 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4565 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4567 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4568 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4570 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4575 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4577 GameObject
* linkedGO
= new GameObject
;
4578 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4579 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4581 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4582 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4584 m_caster
->AddGameObject(linkedGO
);
4596 void Spell::EffectScriptEffect(uint32 effIndex
)
4598 // TODO: we must implement hunter pet summon at login there (spell 6962)
4600 switch(m_spellInfo
->SpellFamilyName
)
4602 case SPELLFAMILY_GENERIC
:
4604 switch(m_spellInfo
->Id
)
4606 // PX-238 Winter Wondervolt TRAP
4609 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4612 for(int j
= 0; j
< 4; ++j
)
4613 if(unitTarget
->HasAura(spells
[j
],0))
4617 uint32 iTmpSpellId
= spells
[urand(0,3)];
4620 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4626 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4629 uint32 spell_id
= 0;
4632 case 1: spell_id
= 8854; break;
4633 default: spell_id
= 8855; break;
4636 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4639 // Brittle Armor - need remove one 24575 Brittle Armor aura
4641 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4643 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4645 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4647 // Orb teleport spells
4661 switch(m_spellInfo
->Id
)
4663 case 25140: spellid
= 32571; break;
4664 case 25143: spellid
= 32572; break;
4665 case 25650: spellid
= 30140; break;
4666 case 25652: spellid
= 30141; break;
4667 case 29128: spellid
= 32568; break;
4668 case 29129: spellid
= 32569; break;
4669 case 35376: spellid
= 25649; break;
4670 case 35727: spellid
= 35730; break;
4675 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4678 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4693 if(!unitTarget
|| !unitTarget
->isAlive())
4696 // Onyxia Scale Cloak
4697 if(unitTarget
->GetDummyAura(22683))
4701 m_caster
->CastSpell(unitTarget
, 22682, true);
4704 // Summon Black Qiraji Battle Tank
4710 // Prevent stacking of mounts
4711 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4713 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4714 if (unitTarget
->GetAreaId() == 3428)
4715 unitTarget
->CastSpell(unitTarget
, 25863, false);
4717 unitTarget
->CastSpell(unitTarget
, 26655, false);
4720 // Piccolo of the Flaming Fire
4723 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4725 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4728 // Mirren's Drinking Hat
4732 switch ( urand(1,6) )
4734 case 1:case 2:case 3:
4735 item
= 23584;break; // Loch Modan Lager
4737 item
= 23585;break; // Stouthammer Lite
4739 item
= 23586;break; // Aerie Peak Pale Ale
4742 DoCreateItem(effIndex
,item
);
4748 // Removes snares and roots.
4749 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4750 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4751 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4755 Aura
*aur
= iter
->second
;
4756 if (!aur
->IsPositive()) //only remove negative spells
4758 // check for mechanic mask
4759 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4761 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4765 next
= Auras
.begin();
4777 unitTarget
->CastSpell(unitTarget
, 41131, true);
4780 // Force Cast - Portal Effect: Sunwell Isle
4786 unitTarget
->CastSpell(unitTarget
, 44870, true);
4789 // Goblin Weather Machine
4798 case 0: spellId
= 46740; break;
4799 case 1: spellId
= 46739; break;
4800 case 2: spellId
= 46738; break;
4801 case 3: spellId
= 46736; break;
4803 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4809 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4812 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4816 // Emblazon Runeblade
4822 unitTarget
->CastSpell(unitTarget
,51771,false);
4828 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4830 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4831 unitTarget
->CastSpell(unitTarget
, damage
, false);
4834 // random spell learn instead placeholder
4835 case 60893: // Northrend Alchemy Research
4836 case 61177: // Northrend Inscription Research
4837 case 61288: // Minor Inscription Research
4838 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4840 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4842 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4846 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4848 Player
* player
= (Player
*)m_caster
;
4850 // need replace effect 0 item by loot
4851 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4853 if(!player
->HasItemCount(reagent_id
,1))
4858 player
->DestroyItemCount (reagent_id
,count
,true);
4860 // create some random items
4861 player
->AutoStoreLootItem(m_spellInfo
->Id
,LootTemplates_Spell
);
4863 // learn random explicit discovery recipe (if any)
4864 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4865 player
->learnSpell(discoveredSpell
,false);
4871 case SPELLFAMILY_WARLOCK
:
4873 switch(m_spellInfo
->Id
)
4875 // Healthstone creating spells
4887 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4888 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4890 if((*i
)->GetId() == 18692)
4895 else if((*i
)->GetId() == 18693)
4902 static uint32
const itypes
[8][3] = {
4903 { 5512,19004,19005}, // Minor Healthstone
4904 { 5511,19006,19007}, // Lesser Healthstone
4905 { 5509,19008,19009}, // Healthstone
4906 { 5510,19010,19011}, // Greater Healthstone
4907 { 9421,19012,19013}, // Major Healthstone
4908 {22103,22104,22105}, // Master Healthstone
4909 {36889,36890,36891}, // Demonic Healthstone
4910 {36892,36893,36894} // Fel Healthstone
4913 switch(m_spellInfo
->Id
)
4916 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4918 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4920 itemtype
=itypes
[2][rank
];break; // Healthstone
4922 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4924 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4926 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4928 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4930 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4934 DoCreateItem( effIndex
, itemtype
);
4940 case SPELLFAMILY_HUNTER
:
4942 switch(m_spellInfo
->Id
)
4948 int32 basePoint
= 0;
4949 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4950 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
4952 Aura
*aura
= (*i
).second
;
4953 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
4955 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
4956 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
4957 if (!(familyFlag
& 0x000000800000C000LL
))
4959 // Refresh aura duration
4960 aura
->RefreshAura();
4962 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
4963 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
4965 spellId
= 53353; // 53353 Chimera Shot - Serpent
4966 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
4968 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
4969 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
4971 spellId
= 53358; // 53358 Chimera Shot - Viper
4972 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
4974 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
4975 if (familyFlag
& 0x0000000000008000LL
)
4976 spellId
= 53359; // 53359 Chimera Shot - Scorpid
4977 // ?? nothing say in spell desc (possibly need addition check)
4978 //if (familyFlag & 0x0000010000000000LL || // dot
4979 // familyFlag & 0x0000100000000000LL) // stun
4981 // spellId = 53366; // 53366 Chimera Shot - Wyvern
4985 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
4993 case SPELLFAMILY_PALADIN
:
4996 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
4998 if(!unitTarget
|| !unitTarget
->isAlive())
5000 uint32 spellId1
= 0;
5001 uint32 spellId2
= 0;
5003 // Judgement self add switch
5004 switch (m_spellInfo
->Id
)
5006 case 41467: break; // Judgement
5007 case 53407: spellId1
= 20184; break; // Judgement of Justice
5008 case 20271: // Judgement of Light
5009 case 57774: spellId1
= 20185; break; // Judgement of Light
5010 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5014 // all seals have aura dummy in 2 effect
5015 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5016 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5018 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5019 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5020 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5022 spellId2
= (*itr
)->GetModifier()->m_amount
;
5023 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5029 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5031 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5035 case SPELLFAMILY_POTION
:
5037 switch(m_spellInfo
->Id
)
5044 unitTarget
->CastSpell(unitTarget
, 28694, true);
5052 // 25% chance of casting a random buff
5053 if(roll_chance_i(75))
5056 // triggered spells are 28703 to 28707
5057 // Note: some sources say, that there was the possibility of
5058 // receiving a debuff. However, this seems to be removed by a patch.
5059 const uint32 spellid
= 28703;
5061 // don't overwrite an existing aura
5062 for(uint8 i
=0; i
<5; i
++)
5063 if(unitTarget
->HasAura(spellid
+i
, 0))
5065 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5074 // 25% chance of casting Nightmare Pollen
5075 if(roll_chance_i(75))
5077 unitTarget
->CastSpell(unitTarget
, 28721, true);
5085 // normal DB scripted effect
5089 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5090 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5093 void Spell::EffectSanctuary(uint32
/*i*/)
5097 //unitTarget->CombatStop();
5099 unitTarget
->CombatStop();
5100 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5101 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5102 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5104 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5108 void Spell::EffectAddComboPoints(uint32
/*i*/)
5113 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5119 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5122 void Spell::EffectDuel(uint32 i
)
5124 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5127 Player
*caster
= (Player
*)m_caster
;
5128 Player
*target
= (Player
*)unitTarget
;
5130 // caster or target already have requested duel
5131 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5134 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5135 // Don't have to check the target's map since you cannot challenge someone across maps
5136 uint32 mapid
= caster
->GetMapId();
5137 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5139 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5143 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5144 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5146 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5150 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5151 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5153 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5157 //CREATE DUEL FLAG OBJECT
5158 GameObject
* pGameObj
= new GameObject
;
5160 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5162 Map
*map
= m_caster
->GetMap();
5163 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
5164 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5165 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5166 m_caster
->GetPositionZ(),
5167 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
5173 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5174 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5175 int32 duration
= GetSpellDuration(m_spellInfo
);
5176 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5177 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5179 m_caster
->AddGameObject(pGameObj
);
5184 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5185 data
<< pGameObj
->GetGUID();
5186 data
<< caster
->GetGUID();
5187 caster
->GetSession()->SendPacket(&data
);
5188 target
->GetSession()->SendPacket(&data
);
5191 DuelInfo
*duel
= new DuelInfo
;
5192 duel
->initiator
= caster
;
5193 duel
->opponent
= target
;
5194 duel
->startTime
= 0;
5195 duel
->startTimer
= 0;
5196 caster
->duel
= duel
;
5198 DuelInfo
*duel2
= new DuelInfo
;
5199 duel2
->initiator
= caster
;
5200 duel2
->opponent
= caster
;
5201 duel2
->startTime
= 0;
5202 duel2
->startTimer
= 0;
5203 target
->duel
= duel2
;
5205 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5206 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5209 void Spell::EffectStuck(uint32
/*i*/)
5211 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5214 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5217 Player
* pTarget
= (Player
*)unitTarget
;
5219 sLog
.outDebug("Spell Effect: Stuck");
5220 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());
5222 if(pTarget
->isInFlight())
5225 // homebind location is loaded always
5226 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5228 // Stuck spell trigger Hearthstone cooldown
5229 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5232 Spell
spell(pTarget
,spellInfo
,true,0);
5233 spell
.SendSpellCooldown();
5236 void Spell::EffectSummonPlayer(uint32
/*i*/)
5238 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5241 // Evil Twin (ignore player summon, but hide this for summoner)
5242 if(unitTarget
->GetDummyAura(23445))
5246 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5248 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5250 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5251 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5252 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5253 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5254 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5257 static ScriptInfo
generateActivateCommand()
5260 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5264 void Spell::EffectActivateObject(uint32 effect_idx
)
5269 static ScriptInfo activateCommand
= generateActivateCommand();
5271 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5273 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5276 void Spell::EffectApplyGlyph(uint32 i
)
5278 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5281 Player
*player
= (Player
*)m_caster
;
5284 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5286 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5288 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5289 player
->SetGlyph(m_glyphIndex
, 0);
5294 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5296 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5298 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5300 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5302 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5303 return; // glyph slot missmatch
5307 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5308 player
->SetGlyph(m_glyphIndex
, glyph
);
5313 void Spell::EffectSummonTotem(uint32 i
)
5316 switch(m_spellInfo
->EffectMiscValueB
[i
])
5318 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5319 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5320 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5321 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5322 // Battle standard case
5323 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5324 // jewelery statue case, like totem without slot
5325 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5329 if(slot
< MAX_TOTEM
)
5331 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5334 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5335 if(OldTotem
&& OldTotem
->isTotem())
5336 ((Totem
*)OldTotem
)->UnSummon();
5341 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5342 team
= ((Player
*)m_caster
)->GetTeam();
5344 Totem
* pTotem
= new Totem
;
5346 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_spellInfo
->EffectMiscValue
[i
], team
))
5352 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5355 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5357 // totem must be at same Z in case swimming caster and etc.
5358 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5359 z
= m_caster
->GetPositionZ();
5361 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5363 if(slot
< MAX_TOTEM
)
5364 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5366 pTotem
->SetOwner(m_caster
->GetGUID());
5367 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5369 int32 duration
=GetSpellDuration(m_spellInfo
);
5370 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5371 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5372 pTotem
->SetDuration(duration
);
5374 if (damage
) // if not spell info, DB values used
5376 pTotem
->SetMaxHealth(damage
);
5377 pTotem
->SetHealth(damage
);
5380 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5382 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5383 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5385 pTotem
->Summon(m_caster
);
5387 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5389 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5390 data
<< uint8(slot
);
5391 data
<< uint64(pTotem
->GetGUID());
5392 data
<< uint32(duration
);
5393 data
<< uint32(m_spellInfo
->Id
);
5394 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5398 void Spell::EffectEnchantHeldItem(uint32 i
)
5400 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5401 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5404 Player
* item_owner
= (Player
*)unitTarget
;
5405 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5411 if(!item
->IsEquipped())
5414 if (m_spellInfo
->EffectMiscValue
[i
])
5416 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5417 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5419 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5421 duration
= 10; //10 seconds for enchants which don't have listed duration
5423 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5427 // Always go to temp enchantment slot
5428 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5430 // Enchantment will not be applied if a different one already exists
5431 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5434 // Apply the temporary enchantment
5435 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5436 item_owner
->ApplyEnchantment(item
,slot
,true);
5440 void Spell::EffectDisEnchant(uint32
/*i*/)
5442 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5445 Player
* p_caster
= (Player
*)m_caster
;
5446 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5449 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5451 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5453 // item will be removed at disenchanting end
5456 void Spell::EffectInebriate(uint32
/*i*/)
5458 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5461 Player
*player
= (Player
*)unitTarget
;
5462 uint16 currentDrunk
= player
->GetDrunkValue();
5463 uint16 drunkMod
= damage
* 256;
5464 if (currentDrunk
+ drunkMod
> 0xFFFF)
5465 currentDrunk
= 0xFFFF;
5467 currentDrunk
+= drunkMod
;
5468 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5471 void Spell::EffectFeedPet(uint32 i
)
5473 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5476 Player
*_player
= (Player
*)m_caster
;
5478 Item
* foodItem
= m_targets
.getItemTarget();
5482 Pet
*pet
= _player
->GetPet();
5489 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5494 _player
->DestroyItemCount(foodItem
,count
,true);
5495 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5497 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5500 void Spell::EffectDismissPet(uint32
/*i*/)
5502 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5505 Pet
* pet
= m_caster
->GetPet();
5507 // not let dismiss dead pet
5508 if(!pet
||!pet
->isAlive())
5511 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5514 void Spell::EffectSummonObject(uint32 i
)
5516 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5519 switch(m_spellInfo
->Effect
[i
])
5521 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5522 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5523 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5524 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5528 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5531 GameObject
* obj
= NULL
;
5533 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5535 if(obj
) obj
->Delete();
5536 m_caster
->m_ObjectSlot
[slot
] = 0;
5539 GameObject
* pGameObj
= new GameObject
;
5541 float rot2
= sin(m_caster
->GetOrientation()/2);
5542 float rot3
= cos(m_caster
->GetOrientation()/2);
5545 // If dest location if present
5546 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5548 x
= m_targets
.m_destX
;
5549 y
= m_targets
.m_destY
;
5550 z
= m_targets
.m_destZ
;
5552 // Summon in random point all other units if location present
5554 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5556 Map
*map
= m_caster
->GetMap();
5557 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
, x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5563 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5564 int32 duration
= GetSpellDuration(m_spellInfo
);
5565 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5566 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5567 m_caster
->AddGameObject(pGameObj
);
5570 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5571 data
<< pGameObj
->GetGUID();
5572 m_caster
->SendMessageToSet(&data
,true);
5574 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5577 void Spell::EffectResurrect(uint32
/*effIndex*/)
5581 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5584 if(unitTarget
->isAlive())
5586 if(!unitTarget
->IsInWorld())
5589 switch (m_spellInfo
->Id
)
5591 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5593 if (roll_chance_i(67))
5595 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5599 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5601 if (roll_chance_i(50))
5603 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5611 Player
* pTarget
= ((Player
*)unitTarget
);
5613 if(pTarget
->isRessurectRequested()) // already have one active request
5616 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5617 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5619 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5620 SendResurrectRequest(pTarget
);
5623 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5625 if(!unitTarget
|| !unitTarget
->isAlive())
5628 if( unitTarget
->m_extraAttacks
)
5631 unitTarget
->m_extraAttacks
= damage
;
5634 void Spell::EffectParry(uint32
/*i*/)
5636 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5637 ((Player
*)unitTarget
)->SetCanParry(true);
5640 void Spell::EffectBlock(uint32
/*i*/)
5642 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5643 ((Player
*)unitTarget
)->SetCanBlock(true);
5646 void Spell::EffectMomentMove(uint32 i
)
5648 if(unitTarget
->isInFlight())
5651 if( m_spellInfo
->rangeIndex
== 1) //self range
5653 uint32 mapid
= m_caster
->GetMapId();
5654 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5658 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5660 unitTarget
->GetPosition(ox
,oy
,oz
);
5662 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5663 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5668 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5671 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5672 ((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));
5674 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5678 void Spell::EffectReputation(uint32 i
)
5680 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5683 Player
*_player
= (Player
*)unitTarget
;
5685 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5687 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5689 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5694 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5697 void Spell::EffectQuestComplete(uint32 i
)
5699 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5702 Player
*_player
= (Player
*)m_caster
;
5704 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5705 _player
->AreaExploredOrEventHappens(quest_id
);
5708 void Spell::EffectSelfResurrect(uint32 i
)
5710 if(!unitTarget
|| unitTarget
->isAlive())
5712 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5714 if(!unitTarget
->IsInWorld())
5723 health
= uint32(-damage
);
5724 mana
= m_spellInfo
->EffectMiscValue
[i
];
5729 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5730 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5731 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5734 Player
*plr
= ((Player
*)unitTarget
);
5735 plr
->ResurrectPlayer(0.0f
);
5737 plr
->SetHealth( health
);
5738 plr
->SetPower(POWER_MANA
, mana
);
5739 plr
->SetPower(POWER_RAGE
, 0 );
5740 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5742 plr
->SpawnCorpseBones();
5747 void Spell::EffectSkinning(uint32
/*i*/)
5749 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5751 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5754 Creature
* creature
= (Creature
*) unitTarget
;
5755 int32 targetLevel
= creature
->getLevel();
5757 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5759 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5760 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5762 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5764 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5766 // Double chances for elites
5767 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5770 void Spell::EffectCharge(uint32
/*i*/)
5772 if(!unitTarget
|| !m_caster
)
5776 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5777 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5778 ((Creature
*)unitTarget
)->StopMoving();
5780 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5781 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5783 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5784 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5786 // not all charge effects used in negative spells
5787 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5788 m_caster
->Attack(unitTarget
,true);
5791 void Spell::EffectSummonCritter(uint32 i
)
5793 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5795 Player
* player
= (Player
*)m_caster
;
5797 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5801 Pet
* old_critter
= player
->GetMiniPet();
5803 // for same pet just despawn
5804 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5806 player
->RemoveMiniPet();
5810 // despawn old pet before summon new
5812 player
->RemoveMiniPet();
5815 Pet
* critter
= new Pet(MINI_PET
);
5817 Map
*map
= m_caster
->GetMap();
5818 uint32 pet_number
= objmgr
.GeneratePetNumber();
5819 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),
5820 map
, pet_entry
, pet_number
))
5822 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5828 // If dest location if present
5829 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5831 x
= m_targets
.m_destX
;
5832 y
= m_targets
.m_destY
;
5833 z
= m_targets
.m_destZ
;
5835 // Summon if dest location not present near caster
5837 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5839 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5841 if(!critter
->IsPositionValid())
5843 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5844 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5849 critter
->SetOwnerGUID(m_caster
->GetGUID());
5850 critter
->SetCreatorGUID(m_caster
->GetGUID());
5851 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5852 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5854 critter
->AIM_Initialize();
5855 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5856 critter
->SetMaxHealth(1);
5857 critter
->SetHealth(1);
5858 critter
->SetLevel(1);
5860 // set timer for unsummon
5861 int32 duration
= GetSpellDuration(m_spellInfo
);
5863 critter
->SetDuration(duration
);
5865 std::string name
= player
->GetName();
5866 name
.append(petTypeSuffix
[critter
->getPetType()]);
5867 critter
->SetName( name
);
5868 player
->SetMiniPet(critter
);
5870 map
->Add((Creature
*)critter
);
5873 void Spell::EffectKnockBack(uint32 i
)
5875 if(!unitTarget
|| !m_caster
)
5878 // Effect only works on players
5879 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5882 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5883 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5885 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5886 data
.append(unitTarget
->GetPackGUID());
5887 data
<< uint32(0); // Sequence
5888 data
<< float(vcos
); // x direction
5889 data
<< float(vsin
); // y direction
5890 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5891 data
<< float(damage
/-10); // Z Movement speed (vertical)
5893 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5896 void Spell::EffectSendTaxi(uint32 i
)
5898 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5901 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5905 std::vector
<uint32
> nodes
;
5908 nodes
[0] = entry
->from
;
5909 nodes
[1] = entry
->to
;
5912 switch(m_spellInfo
->Id
)
5914 case 31606: //Stormcrow Amulet
5917 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5918 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5919 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5922 case 34905: //Stealth Flight
5925 case 45883: //Amber Ledge to Beryl Point
5928 case 46064: //Amber Ledge to Coldarra
5931 case 53335: //Stormwind Harbor Flight - Peaceful
5936 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
5940 void Spell::EffectPlayerPull(uint32 i
)
5942 if(!unitTarget
|| !m_caster
)
5945 // Effect only works on players
5946 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5949 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
5950 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
5952 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5953 data
.append(unitTarget
->GetPackGUID());
5954 data
<< uint32(0); // Sequence
5955 data
<< float(vcos
); // x direction
5956 data
<< float(vsin
); // y direction
5958 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
5959 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
5961 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5964 void Spell::EffectDispelMechanic(uint32 i
)
5969 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
5971 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5972 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
5976 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
5977 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
5979 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
5983 next
= Auras
.begin();
5989 void Spell::EffectSummonDeadPet(uint32
/*i*/)
5991 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5993 Player
*_player
= (Player
*)m_caster
;
5994 Pet
*pet
= _player
->GetPet();
6001 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6002 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6003 pet
->setDeathState( ALIVE
);
6004 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6005 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6007 pet
->AIM_Initialize();
6009 _player
->PetSpellInitialize();
6010 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6013 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6016 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6018 if(!m_caster
->m_TotemSlot
[slot
])
6021 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6022 if(totem
&& totem
->isTotem())
6024 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6025 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6027 mana
+= spellInfo
->manaCost
* damage
/ 100;
6028 ((Totem
*)totem
)->UnSummon();
6032 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6033 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6036 void Spell::EffectDurabilityDamage(uint32 i
)
6038 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6041 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6043 // FIXME: some spells effects have value -1/-2
6044 // Possibly its mean -1 all player equipped items and -2 all items
6047 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6051 // invalid slot value
6052 if(slot
>= INVENTORY_SLOT_BAG_END
)
6055 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6056 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6059 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6061 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6064 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6066 // FIXME: some spells effects have value -1/-2
6067 // Possibly its mean -1 all player equipped items and -2 all items
6070 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6074 // invalid slot value
6075 if(slot
>= INVENTORY_SLOT_BAG_END
)
6081 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6082 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6085 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6090 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6093 void Spell::EffectTransmitted(uint32 effIndex
)
6095 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6097 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6101 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6107 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6109 fx
= m_targets
.m_destX
;
6110 fy
= m_targets
.m_destY
;
6111 fz
= m_targets
.m_destZ
;
6113 //FIXME: this can be better check for most objects but still hack
6114 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6116 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6117 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6121 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6122 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6123 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6125 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6128 Map
*cMap
= m_caster
->GetMap();
6130 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6132 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6133 { // but this is not proper, we really need to ignore not materialized objects
6134 SendCastResult(SPELL_FAILED_NOT_HERE
);
6135 SendChannelUpdate(0);
6139 // replace by water level in this case
6140 fz
= cMap
->GetWaterLevel(fx
,fy
);
6142 // if gameobject is summoning object, it should be spawned right on caster's position
6143 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6145 m_caster
->GetPosition(fx
,fy
,fz
);
6148 GameObject
* pGameObj
= new GameObject
;
6150 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6151 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6157 int32 duration
= GetSpellDuration(m_spellInfo
);
6159 switch(goinfo
->type
)
6161 case GAMEOBJECT_TYPE_FISHINGNODE
:
6163 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6165 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 2, 0.88431775569915771 );
6167 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 3, -0.4668855369091033 );
6168 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6170 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6171 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6175 case 0: lastSec
= 3; break;
6176 case 1: lastSec
= 7; break;
6177 case 2: lastSec
= 13; break;
6178 case 3: lastSec
= 17; break;
6181 duration
= duration
- lastSec
*1000 + FISHING_BOBBER_READY_TIME
*1000;
6184 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6186 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6188 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6189 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6193 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6194 case GAMEOBJECT_TYPE_CHEST
:
6201 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6203 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6205 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6206 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6208 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6209 //m_caster->AddGameObject(pGameObj);
6210 //m_ObjToDel.push_back(pGameObj);
6212 cMap
->Add(pGameObj
);
6214 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6215 data
<< uint64(pGameObj
->GetGUID());
6216 m_caster
->SendMessageToSet(&data
,true);
6218 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6220 GameObject
* linkedGO
= new GameObject
;
6221 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6222 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6224 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6225 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6226 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6227 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6229 linkedGO
->GetMap()->Add(linkedGO
);
6240 void Spell::EffectProspecting(uint32
/*i*/)
6242 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6245 Player
* p_caster
= (Player
*)m_caster
;
6246 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6249 if(itemTarget
->GetCount() < 5)
6252 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6254 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6255 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6256 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6259 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6262 void Spell::EffectMilling(uint32
/*i*/)
6264 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6267 Player
* p_caster
= (Player
*)m_caster
;
6268 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6271 if(itemTarget
->GetCount() < 5)
6274 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6276 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6277 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6278 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6281 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6284 void Spell::EffectSkill(uint32
/*i*/)
6286 sLog
.outDebug("WORLD: SkillEFFECT");
6289 void Spell::EffectSummonDemon(uint32 i
)
6291 float px
= m_targets
.m_destX
;
6292 float py
= m_targets
.m_destY
;
6293 float pz
= m_targets
.m_destZ
;
6295 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6299 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6300 Charmed
->SetLevel(m_caster
->getLevel());
6302 // TODO: Add damage/mana/hp according to level
6304 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6306 // Enslave demon effect, without mana cost and cooldown
6307 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6310 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6314 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6315 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6316 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6317 This is why we use a half sec delay between the visual effect and the resurrection itself */
6318 void Spell::EffectSpiritHeal(uint32
/*i*/)
6321 if(!unitTarget || unitTarget->isAlive())
6323 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6325 if(!unitTarget->IsInWorld())
6328 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6329 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6330 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6331 ((Player*)unitTarget)->SpawnCorpseBones();
6335 // remove insignia spell effect
6336 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6338 sLog
.outDebug("Effect: SkinPlayerCorpse");
6339 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6342 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6345 void Spell::EffectStealBeneficialBuff(uint32 i
)
6347 sLog
.outDebug("Effect: StealBeneficialBuff");
6349 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6352 std::vector
<Aura
*> steal_list
;
6353 // Create dispel mask by dispel type
6354 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6355 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6356 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6358 Aura
*aur
= (*itr
).second
;
6359 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6361 // Need check for passive? this
6362 if (aur
->IsPositive() && !aur
->IsPassive())
6363 steal_list
.push_back(aur
);
6366 // Ok if exist some buffs for dispel try dispel it
6367 if (!steal_list
.empty())
6369 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6370 int32 list_size
= steal_list
.size();
6371 // Dispell N = damage buffs (or while exist buffs for dispel)
6372 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6374 // Random select buff for dispel
6375 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6376 // Not use chance for steal
6377 // TODO possible need do it
6378 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6380 // Remove buff from list for prevent doubles
6381 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6384 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6386 j
= steal_list
.erase(j
);
6393 // Really try steal and send log
6394 if (!success_list
.empty())
6396 int32 count
= success_list
.size();
6397 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6398 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6399 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6400 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6401 data
<< uint8(0); // not used
6402 data
<< uint32(count
); // count
6403 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6405 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6406 data
<< uint32(spellInfo
->Id
); // Spell Id
6407 data
<< uint8(0); // 0 - steals !=0 transfers
6408 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6410 m_caster
->SendMessageToSet(&data
, true);
6415 void Spell::EffectKillCredit(uint32 i
)
6417 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6420 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6423 void Spell::EffectQuestFail(uint32 i
)
6425 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6428 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6431 void Spell::EffectActivateRune(uint32 eff_idx
)
6433 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6436 Player
*plr
= (Player
*)m_caster
;
6438 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6441 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6443 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6445 plr
->SetRuneCooldown(j
, 0);
6450 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6452 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6453 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6456 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6458 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6459 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6462 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);