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 "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
24 #include "UpdateMask.h"
26 #include "ObjectMgr.h"
29 #include "SkillExtraItems.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
51 #include "SocialMgr.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
58 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
60 &Spell::EffectNULL
, // 0
61 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump
, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL
, //154 unused
215 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32
/*i*/)
224 sLog
.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32
/*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i
)
234 if(!unitTarget
|| unitTarget
->isAlive())
237 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
240 if(!unitTarget
->IsInWorld())
243 Player
* pTarget
= ((Player
*)unitTarget
);
245 if(pTarget
->isRessurectRequested()) // already have one active request
248 uint32 health
= damage
;
249 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
250 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
251 SendResurrectRequest(pTarget
);
254 void Spell::EffectInstaKill(uint32
/*i*/)
256 if( !unitTarget
|| !unitTarget
->isAlive() )
260 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
262 uint32 entry
= unitTarget
->GetEntry();
266 case 416: spellID
=18789; break; //imp
267 case 417: spellID
=18792; break; //fellhunter
268 case 1860: spellID
=18790; break; //void
269 case 1863: spellID
=18791; break; //succubus
270 case 17252: spellID
=35701; break; //fellguard
272 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
276 m_caster
->CastSpell(m_caster
,spellID
,true);
279 if(m_caster
==unitTarget
) // prevent interrupt message
282 uint32 health
= unitTarget
->GetHealth();
283 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i
)
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage
= m_spellInfo
->CalculateSimpleValue(i
);
296 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
298 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
299 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
300 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
,damage
);
303 void Spell::EffectSchoolDMG(uint32 effect_idx
)
305 if( unitTarget
&& unitTarget
->isAlive())
307 switch(m_spellInfo
->SpellFamilyName
)
309 case SPELLFAMILY_GENERIC
:
312 if(m_spellInfo
->SpellIconID
== 2269 )
314 damage
+= rand()%2 ? damage
: 0;
317 switch(m_spellInfo
->Id
) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
330 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
331 if(ihit
->effectMask
& (1<<effect_idx
))
334 damage
/= count
; // divide to all targets
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage
= unitTarget
->GetHealth() / 2;
345 // Intercept (warrior spell trigger)
349 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
356 case SPELLFAMILY_MAGE
:
359 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
361 m_caster
->CastSpell(m_caster
,36032,true);
365 case SPELLFAMILY_WARRIOR
:
368 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
370 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
373 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000020000000000LL
)
374 damage
+= int32(m_caster
->GetShieldBlockValue());
376 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
378 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
379 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
383 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
386 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
390 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
392 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
397 case SPELLFAMILY_WARLOCK
:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
404 damage
+= int32(damage
*0.25f
);
408 case SPELLFAMILY_PRIEST
:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
412 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
415 case SPELLFAMILY_DRUID
:
418 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
422 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
423 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
424 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
425 m_caster
->SetPower(POWER_ENERGY
,0);
428 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
430 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
433 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
435 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
439 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
441 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
442 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
443 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
445 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
451 case SPELLFAMILY_ROGUE
:
454 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
462 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
463 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
464 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
465 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
470 // count consumed deadly poison doses at target
473 uint32 spellId
= poison
->GetId();
474 uint32 doses
= poison
->GetStackAmount();
477 for (int i
=0; i
< doses
; i
++)
478 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
480 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster
->GetDummyAura(37169))
484 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
488 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
490 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
492 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
493 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster
->GetDummyAura(37169))
501 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
503 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
506 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
508 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
511 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
513 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
517 case SPELLFAMILY_HUNTER
:
520 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
522 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
525 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
527 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
530 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
532 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
535 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
537 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
538 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
540 // Explosive Trap Effect
541 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
543 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
547 case SPELLFAMILY_PALADIN
:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
552 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
553 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
554 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
555 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
558 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
559 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
560 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
562 stacks
= (*itr
)->GetStackAmount();
565 // + 10% for each application of Holy Vengeance on the target
567 damage
+= damage
* stacks
* 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
572 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
573 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
574 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
575 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
580 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
581 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
582 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
583 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
588 // Add main hand dps * effect[2] amount
589 float averange
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
590 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
591 damage
+= count
* int32(averange
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
593 // Shield of Righteousness
594 else if(m_spellInfo
->SpellFamilyFlags
&0x0010000000000000LL
)
596 damage
+=int32(m_caster
->GetShieldBlockValue());
607 void Spell::EffectDummy(uint32 i
)
609 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
612 // selection by spell family
613 switch(m_spellInfo
->SpellFamilyName
)
615 case SPELLFAMILY_GENERIC
:
617 switch(m_spellInfo
->Id
)
619 case 8063: // Deviate Fish
621 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
627 case 1: spell_id
= 8064; break; // Sleepy
628 case 2: spell_id
= 8065; break; // Invigorate
629 case 3: spell_id
= 8066; break; // Shrink
630 case 4: spell_id
= 8067; break; // Party Time!
631 case 5: spell_id
= 8068; break; // Healthy Spirit
633 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
636 case 8213: // Savory Deviate Delight
638 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
645 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
647 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
649 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
657 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
671 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
673 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
675 switch (m_spellInfo
->Id
)
677 case 12850: damage
*= 0.2f
; break;
678 case 12162: damage
*= 0.4f
; break;
679 case 12868: damage
*= 0.6f
; break;
681 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
685 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
686 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
689 case 13120: // net-o-matic
696 uint32 roll
= urand(0, 99);
698 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
700 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
705 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell
|| !unitTarget
)
714 switch(m_triggeredByAuraSpell
->Id
)
716 case 26467: // Persistent Shield
717 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
720 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
731 Creature
* creatureTarget
= (Creature
*)unitTarget
;
732 creatureTarget
->setDeathState(JUST_DIED
);
733 creatureTarget
->RemoveCorpse();
734 creatureTarget
->SetHealth(0); // just for nice GM-mode view
737 case 16589: // Noggenfogger Elixir
739 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
745 case 1: spell_id
= 16595; break;
746 case 2: spell_id
= 16593; break;
747 default:spell_id
= 16591; break;
750 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
753 case 17251: // Spirit Healer Res
755 if(!unitTarget
|| !m_originalCaster
)
758 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
760 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
761 data
<< unitTarget
->GetGUID();
762 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
766 case 17271: // Test Fetid Skull
768 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
771 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
773 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
776 case 20577: // Cannibalize
778 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
785 Creature
* creatureTarget
= (Creature
*)unitTarget
;
786 if(creatureTarget
->isPet())
789 GameObject
* pGameObj
= new GameObject
;
791 Map
*map
= creatureTarget
->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
795 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
796 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1) )
802 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
803 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
804 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
805 pGameObj
->SetSpellId(m_spellInfo
->Id
);
807 creatureTarget
->setDeathState(JUST_DIED
);
808 creatureTarget
->RemoveCorpse();
809 creatureTarget
->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
814 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
815 data
<< uint64(pGameObj
->GetGUID());
816 m_caster
->SendMessageToSet(&data
,true);
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem
) return;
822 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem
) return;
826 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem
) return;
830 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem
) return;
834 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r
= irand(0, 119);
839 if ( r
< 20 ) // 1/6 polymorph
840 m_caster
->CastSpell(m_caster
,23444,true);
841 else if ( r
< 100 ) // 4/6 evil twin
842 m_caster
->CastSpell(m_caster
,23445,true);
843 else // 1/6 miss the target
844 m_caster
->CastSpell(m_caster
,36902,true);
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster
->CastSpell(m_caster
,23441,true);
851 m_caster
->CastSpell(m_caster
,23446,true);
853 case 23645: // Hourglass Sand
854 m_caster
->RemoveAurasDueToSpell(23170);
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster
->CastSpell(m_caster
,23782,true);
858 m_caster
->CastSpell(m_caster
,23783,true);
860 case 25860: // Reindeer Transformation
862 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
865 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
866 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
868 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed
>= 4.1f
)
872 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
873 else if (flyspeed
>= 3.8f
)
874 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
875 else if (flyspeed
>= 1.6f
)
876 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
877 else if (speed
>= 2.0f
)
878 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
880 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
889 m_caster
->CastSpell(unitTarget
,29294,true);
892 case 28730: // Arcane Torrent (Mana)
894 Aura
* dummy
= m_caster
->GetDummyAura(28734);
897 int32 bp
= damage
* dummy
->GetStackAmount();
898 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
899 m_caster
->RemoveAurasDueToSpell(28734);
903 case 29200: // Purify Helboar Meat
905 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
908 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
910 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
913 case 29858: // Soulshatter
914 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
915 m_caster
->CastSpell(unitTarget
,32835,true);
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem
) return;
919 if(roll_chance_i(86)) // success
920 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
921 else // backfire in 14% casts
922 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
924 case 30507: // Poultryizer
925 if (!m_CastItem
) return;
926 if(roll_chance_i(80)) // success
927 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
929 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
931 case 33060: // Make a Wish
933 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
940 case 1: spell_id
= 33053; break;
941 case 2: spell_id
= 33057; break;
942 case 3: spell_id
= 33059; break;
943 case 4: spell_id
= 33062; break;
944 case 5: spell_id
= 33064; break;
947 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
953 switch(m_caster
->GetAreaId())
955 case 3900: spell_id
= 35743; break;
956 case 3742: spell_id
= 35744; break;
960 m_caster
->CastSpell(m_caster
,spell_id
,true);
963 case 37674: // Chaos Blast
968 int32 basepoints0
= 100;
969 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
978 case 1: newitemid
= 32688; break;
979 case 2: newitemid
= 32689; break;
980 case 3: newitemid
= 32690; break;
981 case 4: newitemid
= 32691; break;
982 case 5: newitemid
= 32692; break;
983 case 6: newitemid
= 32693; break;
984 case 7: newitemid
= 32700; break;
985 case 8: newitemid
= 32701; break;
986 case 9: newitemid
= 32702; break;
987 case 10: newitemid
= 32703; break;
988 case 11: newitemid
= 32704; break;
989 case 12: newitemid
= 32705; break;
990 case 13: newitemid
= 32706; break;
991 case 14: newitemid
= 32707; break;
992 case 15: newitemid
= 32708; break;
993 case 16: newitemid
= 32709; break;
994 case 17: newitemid
= 32710; break;
995 case 18: newitemid
= 32711; break;
996 case 19: newitemid
= 32712; break;
997 case 20: newitemid
= 32713; break;
1002 DoCreateItem(i
,newitemid
);
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1021 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1023 creatureTarget
->setDeathState(JUST_DIED
);
1024 creatureTarget
->RemoveCorpse();
1025 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1031 case 34665: //Administer Antidote
1033 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1039 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1043 uint32 health
= tempSummon
->GetHealth();
1045 float x
= tempSummon
->GetPositionX();
1046 float y
= tempSummon
->GetPositionY();
1047 float z
= tempSummon
->GetPositionZ();
1048 float o
= tempSummon
->GetOrientation();
1049 tempSummon
->UnSummon();
1051 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1055 pCreature
->SetHealth(health
);
1056 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992,pCreature
);
1058 if (pCreature
->AI())
1059 pCreature
->AI()->AttackStart(m_caster
);
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster
->CastSpell(m_caster
, 45009, true);
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster
->CastSpell(m_caster
, 45088, true);
1075 case 50243: // Teach Language
1077 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1083 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1085 // 1000001 - gnomish binary
1086 m_caster
->CastSpell(m_caster
, 50242, true);
1090 // 01001000 - goblin binary
1091 m_caster
->CastSpell(m_caster
, 50246, true);
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1101 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1102 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1104 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1113 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1114 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1116 if (m_caster
->HasAura(reqAuraID
,0))
1117 m_caster
->CastSpell(m_caster
,spellID
,true,NULL
);
1121 return; // additional data for dummy[0]
1128 m_caster
->CastSpell(m_caster
,54586,true);
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo
->SpellIconID
)
1139 // Berserking (troll racial traits)
1142 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1143 int32 melee_mod
= 10;
1144 if (healthPerc
<= 40)
1146 if (healthPerc
< 100 && healthPerc
> 40)
1147 melee_mod
= 10+(100-healthPerc
)/3;
1149 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1
= (5-melee_mod
);
1151 int32 hasteModBasePoints2
= 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1155 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1161 case SPELLFAMILY_MAGE
:
1162 switch(m_spellInfo
->Id
)
1164 case 11958: // Cold Snap
1166 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1173 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1176 uint32 classspell
= itr
->first
;
1177 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1179 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1180 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1181 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1183 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1185 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1186 data
<< uint32(classspell
);
1187 data
<< uint64(m_caster
->GetGUID());
1188 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1195 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1205 case SPELLFAMILY_WARRIOR
:
1207 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1209 int32 chargeBasePoints0
= damage
;
1210 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1214 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1219 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1220 // Glyph of Execution bonus
1221 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1222 rage
+=aura
->GetModifier()->m_amount
;
1224 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1225 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1226 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1227 m_caster
->SetPower(POWER_RAGE
,0);
1231 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1235 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1239 switch(m_spellInfo
->Id
)
1246 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1252 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1253 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1259 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1264 case SPELLFAMILY_WARLOCK
:
1266 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1268 // In 303 exist spirit depend
1269 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1270 switch (m_spellInfo
->Id
)
1272 case 1454: damage
+=spirit
; break;
1273 case 1455: damage
+=spirit
*15/10; break;
1274 case 1456: damage
+=spirit
*2; break;
1275 case 11687: damage
+=spirit
*25/10; break;
1279 case 57946: damage
+=spirit
*3; break;
1281 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1284 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1285 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1286 if(int32(unitTarget
->GetHealth()) > damage
)
1288 // Shouldn't Appear in Combat Log
1289 unitTarget
->ModifyHealth(-damage
);
1291 int32 mana
= damage
;
1292 // Improved Life Tap mod
1293 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1294 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1296 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1297 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1299 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1302 int32 manaFeedVal
= 0;
1303 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1304 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1306 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1307 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1311 manaFeedVal
= manaFeedVal
* mana
/ 100;
1312 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1316 SendCastResult(SPELL_FAILED_FIZZLE
);
1320 case SPELLFAMILY_PRIEST
:
1322 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1329 switch(m_spellInfo
->Id
)
1331 case 47540: hurt
= 47758; heal
= 47757; break;
1332 case 53005: hurt
= 53001; heal
= 52986; break;
1333 case 53006: hurt
= 53002; heal
= 52987; break;
1334 case 53007: hurt
= 53003; heal
= 52988; break;
1336 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1339 if (m_caster
->IsFriendlyTo(unitTarget
))
1340 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1342 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1346 case SPELLFAMILY_DRUID
:
1348 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000100LL
)
1350 //Shapeshifting into an animal form or mounting cancels the effect.
1351 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1353 if(m_triggeredByAuraSpell
)
1354 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1358 //Any effect which causes you to lose control of your character will supress the starfall effect.
1359 if(m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1362 switch(m_spellInfo
->Id
)
1364 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1365 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1366 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1367 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1369 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1374 case SPELLFAMILY_ROGUE
:
1375 switch(m_spellInfo
->Id
)
1379 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1382 Player
*pCaster
= ((Player
*)m_caster
);
1384 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1388 // all poison enchantments is temporary
1389 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1393 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1397 for (int s
=0;s
<3;s
++)
1399 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1402 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1403 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1406 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1409 m_caster
->CastSpell(unitTarget
, 5940, true);
1412 case 14185: // Preparation Rogue
1414 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1417 //immediately finishes the cooldown on certain Rogue abilities
1418 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1419 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1421 uint32 classspell
= itr
->first
;
1422 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1424 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1426 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1428 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1429 data
<< uint32(classspell
);
1430 data
<< uint64(m_caster
->GetGUID());
1431 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1436 case 31231: // Cheat Death
1438 m_caster
->CastSpell(m_caster
,45182,true);
1443 case SPELLFAMILY_HUNTER
:
1445 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1447 if( !unitTarget
|| !unitTarget
->isAlive())
1452 // check dazed affect
1453 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1454 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1456 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1468 switch(m_spellInfo
->Id
)
1470 case 23989: //Readiness talent
1472 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1475 //immediately finishes the cooldown for hunter abilities
1476 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1477 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1479 uint32 classspell
= itr
->first
;
1480 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1482 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1484 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1486 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1487 data
<< uint32(classspell
);
1488 data
<< uint64(m_caster
->GetGUID());
1489 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1494 case 37506: // Scatter Shot
1496 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1499 // break Auto Shot and autohit
1500 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1501 m_caster
->AttackStop();
1502 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1507 case SPELLFAMILY_PALADIN
:
1508 switch(m_spellInfo
->SpellIconID
)
1510 case 156: // Holy Shock
1518 switch(m_spellInfo
->Id
)
1520 case 20473: hurt
= 25912; heal
= 25914; break;
1521 case 20929: hurt
= 25911; heal
= 25913; break;
1522 case 20930: hurt
= 25902; heal
= 25903; break;
1523 case 27174: hurt
= 27176; heal
= 27175; break;
1524 case 33072: hurt
= 33073; heal
= 33074; break;
1525 case 48824: hurt
= 48822; heal
= 48820; break;
1526 case 48825: hurt
= 48823; heal
= 48821; break;
1528 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1532 if(m_caster
->IsFriendlyTo(unitTarget
))
1533 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1535 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1539 case 561: // Judgement of command
1544 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1545 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1549 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1551 // decreased damage (/2) for non-stunned target.
1552 SpellModifier
*mod
= new SpellModifier
;
1553 mod
->op
= SPELLMOD_DAMAGE
;
1555 mod
->type
= SPELLMOD_PCT
;
1556 mod
->spellId
= m_spellInfo
->Id
;
1557 mod
->mask
= 0x0000020000000000LL
;
1560 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1561 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1563 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1566 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1572 switch(m_spellInfo
->Id
)
1574 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1579 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1582 case 31789: // Righteous Defense (step 1)
1584 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1586 // non-standard cast requirement check
1587 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1589 // clear cooldown at fail
1590 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1592 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1594 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1595 data
<< uint32(m_spellInfo
->Id
);
1596 data
<< uint64(m_caster
->GetGUID());
1597 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1600 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1604 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1605 // Clear targets for eff 1
1606 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1607 ihit
->effectMask
&= ~(1<<1);
1609 // not empty (checked)
1610 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1612 // chance to be selected from list
1613 float chance
= 100.0f
/attackers
.size();
1615 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1617 if(!roll_chance_f(chance
))
1620 AddUnitTarget((*aItr
), 1);
1623 // now let next effect cast spell at each target.
1626 case 37877: // Blessing of Faith
1631 uint32 spell_id
= 0;
1632 switch(unitTarget
->getClass())
1634 case CLASS_DRUID
: spell_id
= 37878; break;
1635 case CLASS_PALADIN
: spell_id
= 37879; break;
1636 case CLASS_PRIEST
: spell_id
= 37880; break;
1637 case CLASS_SHAMAN
: spell_id
= 37881; break;
1638 default: return; // ignore for not healing classes
1641 m_caster
->CastSpell(m_caster
,spell_id
,true);
1646 case SPELLFAMILY_SHAMAN
:
1647 //Shaman Rockbiter Weapon
1648 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1650 // TODO: use expect spell for enchant (if exist talent)
1651 // In 3.0.3 no mods present for rockbiter
1652 uint32 spell_id
= 0;
1653 switch(m_spellInfo
->Id
)
1655 case 8017: spell_id
= 36494; break; // Rank 1
1656 case 8018: spell_id
= 36750; break; // Rank 2
1657 case 8019: spell_id
= 36755; break; // Rank 3
1658 case 10399: spell_id
= 36759; break; // Rank 4
1660 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1664 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1668 sLog
.outError("WORLD: unknown spell id %i", spell_id
);
1672 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1675 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1677 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1679 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1681 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1683 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1684 // at calculation applied affect from Elemental Weapons talent
1685 // real enchantment damage-1
1686 spell
->m_currentBasePoints
[1] = damage
-1;
1688 SpellCastTargets targets
;
1689 targets
.setItemTarget( item
);
1690 spell
->prepare(&targets
);
1696 // Healing Stream Totem
1697 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1699 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1702 // Mana Spring Totem
1703 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1705 if(unitTarget
->getPowerType()!=POWER_MANA
)
1707 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1710 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1712 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1714 // Glyph of Mana Tide
1715 Unit
*owner
= m_caster
->GetOwner();
1717 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1718 damage
+=dummy
->GetModifier()->m_amount
;
1719 // Regenerate 6% of Total Mana Every 3 secs
1720 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1721 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1725 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1727 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1729 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1732 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1733 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1734 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1736 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1737 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1738 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1740 m_damage
+= m_damage
* damage
/ 100;
1748 case SPELLFAMILY_DEATHKNIGHT
:
1750 if(m_spellInfo
->SpellFamilyFlags
& 0x002000LL
)
1752 if(m_caster
->IsFriendlyTo(unitTarget
))
1754 if(unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1757 int32 bp
= damage
* 1.5f
;
1758 m_caster
->CastCustomSpell(unitTarget
,47633,&bp
,NULL
,NULL
,true);
1763 m_caster
->CastCustomSpell(unitTarget
,47632,&bp
,NULL
,NULL
,true);
1771 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1773 m_caster
->AddPetAura(petSpell
);
1777 // Script based implementation. Must be used only for not good for implementation in core spell effects
1778 // So called only for not proccessed cases
1780 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
1781 else if(unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
1782 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
1784 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
1787 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1789 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1792 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1796 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1801 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1804 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1806 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1807 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1811 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1816 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1818 SpellCastTargets targets
;
1819 targets
.setUnitTarget( unitTarget
);
1820 spell
->prepare(&targets
);
1822 m_caster
->SetCurrentCastedSpell(spell
);
1823 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1827 void Spell::EffectForceCast(uint32 i
)
1832 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1835 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1839 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1843 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1846 void Spell::EffectTriggerSpell(uint32 i
)
1848 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1851 switch(triggered_spell_id
)
1856 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1857 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1858 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1860 // if this spell is given to NPC it must handle rest by it's own AI
1861 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1864 // get highest rank of the Stealth spell
1866 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1867 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1869 // only highest rank is shown in spell book, so simply check if shown in spell book
1870 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1873 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1877 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1879 spellId
= spellInfo
->Id
;
1884 // no Stealth spell found
1888 // reset cooldown on it if needed
1889 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1890 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1892 m_caster
->CastSpell(m_caster
, spellId
, true);
1896 case 23770: // Sayge's Dark Fortune of *
1897 // not exist, common cooldown can be implemented in scripts if need.
1899 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1902 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1906 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1907 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1910 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1913 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1917 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1918 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1921 // Righteous Defense
1924 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1930 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1931 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1933 // remove all harmful spells on you...
1934 if( // ignore positive and passive auras
1935 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1936 // ignore physical auras
1937 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1939 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1940 iter
= Auras
.begin();
1945 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1948 if (Unit
*pet
= m_caster
->GetPet())
1949 pet
->CastSpell(pet
, 28305, true);
1955 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1959 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1963 // some triggered spells require specific equipment
1964 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1966 // main hand weapon required
1967 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1969 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1971 // skip spell if no weapon in slot or broken
1972 if(!item
|| item
->IsBroken() )
1975 // skip spell if weapon not fit to triggered spell
1976 if(!item
->IsFitToSpellRequirements(spellInfo
))
1980 // offhand hand weapon required
1981 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1983 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1985 // skip spell if no weapon in slot or broken
1986 if(!item
|| item
->IsBroken() )
1989 // skip spell if weapon not fit to triggered spell
1990 if(!item
->IsFitToSpellRequirements(spellInfo
))
1995 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1996 bool instant
= false;
1997 for(uint32 j
= i
+1; j
< 3; ++j
)
1999 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
2009 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
2012 m_TriggerSpells
.push_back(spellInfo
);
2015 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2017 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2020 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2024 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2025 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2030 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2032 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2035 void Spell::EffectJump(uint32 i
)
2037 if(m_caster
->isInFlight())
2040 // Init dest coordinates
2042 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2044 x
= m_targets
.m_destX
;
2045 y
= m_targets
.m_destY
;
2046 z
= m_targets
.m_destZ
;
2048 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2050 // explicit cast data from client or server-side cast
2051 // some spell at client send caster
2052 Unit
* pTarget
= NULL
;
2053 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2054 pTarget
= m_targets
.getUnitTarget();
2055 else if(unitTarget
->getVictim())
2056 pTarget
= m_caster
->getVictim();
2057 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2058 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2060 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2063 o
= m_caster
->GetOrientation();
2067 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2068 o
= m_caster
->GetOrientation();
2070 else if(gameObjTarget
)
2072 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2073 o
= m_caster
->GetOrientation();
2077 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2081 m_caster
->NearTeleportTo(x
,y
,z
,o
,true);
2084 void Spell::EffectTeleportUnits(uint32 i
)
2086 if(!unitTarget
|| unitTarget
->isInFlight())
2089 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2091 case TARGET_INNKEEPER_COORDINATES
:
2093 // Only players can teleport to innkeeper
2094 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2097 ((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);
2100 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2102 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2105 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2109 if(st
->target_mapId
==unitTarget
->GetMapId())
2110 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2111 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2112 ((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);
2115 case TARGET_BEHIND_VICTIM
:
2117 Unit
*pTarget
= NULL
;
2119 // explicit cast data from client or server-side cast
2120 // some spell at client send caster
2121 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2122 pTarget
= m_targets
.getUnitTarget();
2123 else if(unitTarget
->getVictim())
2124 pTarget
= unitTarget
->getVictim();
2125 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2126 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2128 // Init dest coordinates
2129 float x
= m_targets
.m_destX
;
2130 float y
= m_targets
.m_destY
;
2131 float z
= m_targets
.m_destZ
;
2132 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2133 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2138 // If not exist data for dest location - return
2139 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2141 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2144 // Init dest coordinates
2145 uint32 mapid
= m_caster
->GetMapId();
2146 float x
= m_targets
.m_destX
;
2147 float y
= m_targets
.m_destY
;
2148 float z
= m_targets
.m_destZ
;
2149 float orientation
= unitTarget
->GetOrientation();
2151 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2156 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2157 switch ( m_spellInfo
->Id
)
2159 // Dimensional Ripper - Everlook
2162 int32 r
= irand(0, 119);
2163 if ( r
>= 70 ) // 7/12 success
2165 if ( r
< 100 ) // 4/12 evil twin
2166 m_caster
->CastSpell(m_caster
,23445,true);
2168 m_caster
->CastSpell(m_caster
,23449,true);
2172 // Ultrasafe Transporter: Toshley's Station
2175 if ( roll_chance_i(50) ) // 50% success
2177 int32 rand_eff
= urand(1,7);
2181 // soul split - evil
2182 m_caster
->CastSpell(m_caster
,36900,true);
2185 // soul split - good
2186 m_caster
->CastSpell(m_caster
,36901,true);
2189 // Increase the size
2190 m_caster
->CastSpell(m_caster
,36895,true);
2193 // Decrease the size
2194 m_caster
->CastSpell(m_caster
,36893,true);
2199 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2200 m_caster
->CastSpell(m_caster
,36897,true);
2202 m_caster
->CastSpell(m_caster
,36899,true);
2207 m_caster
->CastSpell(m_caster
,36940,true);
2211 m_caster
->CastSpell(m_caster
,23445,true);
2217 // Dimensional Ripper - Area 52
2220 if ( roll_chance_i(50) ) // 50% success
2222 int32 rand_eff
= urand(1,4);
2226 // soul split - evil
2227 m_caster
->CastSpell(m_caster
,36900,true);
2230 // soul split - good
2231 m_caster
->CastSpell(m_caster
,36901,true);
2234 // Increase the size
2235 m_caster
->CastSpell(m_caster
,36895,true);
2240 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2241 m_caster
->CastSpell(m_caster
,36897,true);
2243 m_caster
->CastSpell(m_caster
,36899,true);
2253 void Spell::EffectApplyAura(uint32 i
)
2258 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2259 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2260 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2263 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2267 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2269 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2271 // Now Reduce spell duration using data received at spell hit
2272 int32 duration
= Aur
->GetAuraMaxDuration();
2273 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2274 Aur
->setDiminishGroup(m_diminishGroup
);
2276 // if Aura removed and deleted, do not continue.
2277 if(duration
== 0 && !(Aur
->IsPermanent()))
2283 if(duration
!= Aur
->GetAuraMaxDuration())
2285 Aur
->SetAuraMaxDuration(duration
);
2286 Aur
->SetAuraDuration(duration
);
2289 bool added
= unitTarget
->AddAura(Aur
);
2291 // Aura not added and deleted in AddAura call;
2295 // found crash at character loading, broken pointer to Aur...
2296 // Aur was deleted in AddAura()...
2300 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2301 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2302 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2305 void Spell::EffectUnlearnSpecialization( uint32 i
)
2307 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2310 Player
*_player
= (Player
*)unitTarget
;
2311 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2313 _player
->removeSpell(spellToUnlearn
);
2315 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2318 void Spell::EffectPowerDrain(uint32 i
)
2320 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2323 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2327 if(!unitTarget
->isAlive())
2329 if(unitTarget
->getPowerType() != drain_power
)
2334 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2336 //add spell damage bonus
2337 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2339 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2340 uint32 power
= damage
;
2341 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2342 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2345 if(curPower
< power
)
2346 new_damage
= curPower
;
2350 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2352 // Don`t restore from self drain
2353 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2355 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2356 if(manaMultiplier
==0)
2359 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2360 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2362 int32 gain
= int32(new_damage
*manaMultiplier
);
2364 m_caster
->ModifyPower(POWER_MANA
,gain
);
2366 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2370 void Spell::EffectSendEvent(uint32 EffectIndex
)
2373 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2375 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2376 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2379 void Spell::EffectPowerBurn(uint32 i
)
2381 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2384 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2388 if(!unitTarget
->isAlive())
2390 if(unitTarget
->getPowerType()!=powertype
)
2395 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2397 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2398 uint32 power
= damage
;
2399 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2400 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2402 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2404 unitTarget
->ModifyPower(powertype
,-new_damage
);
2405 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2407 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2408 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2410 new_damage
= int32(new_damage
*multiplier
);
2411 m_damage
+=new_damage
;
2414 void Spell::EffectHeal( uint32
/*i*/ )
2416 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2418 // Try to get original caster
2419 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2421 // Skip if m_originalCaster not available
2425 int32 addhealth
= damage
;
2427 // Vessel of the Naaru (Vial of the Sunwell trinket)
2428 if (m_spellInfo
->Id
== 45064)
2430 // Amount of heal - depends from stacked Holy Energy
2431 int damageAmount
= 0;
2432 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2433 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2434 if((*i
)->GetId() == 45062)
2435 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2437 m_caster
->RemoveAurasDueToSpell(45062);
2439 addhealth
+= damageAmount
;
2441 // Swiftmend - consumes Regrowth or Rejuvenation
2442 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2444 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2445 // find most short by duration
2446 Aura
*targetAura
= NULL
;
2447 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2449 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2450 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2452 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2459 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2465 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2470 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2471 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2472 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2474 addhealth
+= tickheal
* tickcount
;
2477 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2479 m_healing
+=addhealth
;
2483 void Spell::EffectHealPct( uint32
/*i*/ )
2485 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2487 // Try to get original caster
2488 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2490 // Skip if m_originalCaster not available
2494 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2495 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2497 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2498 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2500 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2501 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2502 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2506 void Spell::EffectHealMechanical( uint32
/*i*/ )
2508 // Mechanic creature type should be correctly checked by targetCreatureType field
2509 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2511 // Try to get original caster
2512 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2514 // Skip if m_originalCaster not available
2518 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2519 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2520 unitTarget
->ModifyHealth( int32(damage
) );
2524 void Spell::EffectHealthLeech(uint32 i
)
2528 if(!unitTarget
->isAlive())
2534 sLog
.outDebug("HealthLeech :%i", damage
);
2536 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2538 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2539 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2541 int32 new_damage
= int32(damage
*multiplier
);
2542 uint32 curHealth
= unitTarget
->GetHealth();
2543 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2544 if(curHealth
< new_damage
)
2545 new_damage
= curHealth
;
2547 if(m_caster
->isAlive())
2549 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2551 m_caster
->ModifyHealth(new_damage
);
2553 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2554 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2556 // m_healthLeech+=tmpvalue;
2557 // m_damage+=new_damage;
2560 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2562 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2565 Player
* player
= (Player
*)unitTarget
;
2567 uint32 newitemid
= itemtype
;
2568 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2571 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2577 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2578 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2580 int32 basePoints
= m_currentBasePoints
[i
];
2581 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2583 num_to_add
= basePoints
+ irand(1, randomPoints
);
2585 num_to_add
= basePoints
+ 1;
2587 else if (pProto
->MaxCount
== 1)
2589 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2591 int32 basePoints
= m_currentBasePoints
[i
];
2592 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2593 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2600 if (num_to_add
> pProto
->GetMaxStackSize())
2601 num_to_add
= pProto
->GetMaxStackSize();
2603 // init items_count to 1, since 1 item will be created regardless of specialization
2605 // the chance to create additional items
2606 float additionalCreateChance
=0.0f
;
2607 // the maximum number of created additional items
2608 uint8 additionalMaxNum
=0;
2609 // get the chance and maximum number for creating extra items
2610 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2612 // roll with this chance till we roll not to create or we create the max num
2613 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2617 // really will be created more items
2618 num_to_add
*= items_count
;
2620 // can the player store the new item?
2621 ItemPosCountVec dest
;
2622 uint32 no_space
= 0;
2623 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2624 if( msg
!= EQUIP_ERR_OK
)
2626 // convert to possible store amount
2627 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2628 num_to_add
-= no_space
;
2631 // if not created by another reason from full inventory or unique items amount limitation
2632 player
->SendEquipError( msg
, NULL
, NULL
);
2639 // create the new item and store it
2640 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2642 // was it successful? return error if not
2645 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2649 // set the "Crafted by ..." property of the item
2650 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2651 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2653 // send info to the client
2655 player
->SendNewItem(pItem
, num_to_add
, true, true);
2657 // we succeeded in creating at least one item, so a levelup is possible
2658 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2661 // for battleground marks send by mail if not add all expected
2664 BattleGroundTypeId bgType
;
2665 switch(m_spellInfo
->Id
)
2667 case SPELL_AV_MARK_WINNER
:
2668 case SPELL_AV_MARK_LOSER
:
2669 bgType
= BATTLEGROUND_AV
;
2671 case SPELL_WS_MARK_WINNER
:
2672 case SPELL_WS_MARK_LOSER
:
2673 bgType
= BATTLEGROUND_WS
;
2675 case SPELL_AB_MARK_WINNER
:
2676 case SPELL_AB_MARK_LOSER
:
2677 bgType
= BATTLEGROUND_AB
;
2683 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2684 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2688 void Spell::EffectCreateItem(uint32 i
)
2690 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2693 void Spell::EffectCreateItem2(uint32 i
)
2695 // special case: generate using spell_loot_template
2696 if(!m_spellInfo
->EffectItemType
[i
])
2698 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2701 // create some random items
2702 ((Player
*)m_caster
)->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
2705 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2708 void Spell::EffectPersistentAA(uint32 i
)
2710 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2712 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2713 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2715 int32 duration
= GetSpellDuration(m_spellInfo
);
2716 DynamicObject
* dynObj
= new DynamicObject
;
2717 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
))
2722 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2723 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2724 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2725 m_caster
->AddDynObject(dynObj
);
2726 dynObj
->GetMap()->Add(dynObj
);
2729 void Spell::EffectEnergize(uint32 i
)
2733 if(!unitTarget
->isAlive())
2736 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2739 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2741 // Some level depends spells
2744 switch (m_spellInfo
->Id
)
2748 level_diff
= m_caster
->getLevel() - 40;
2753 level_diff
= m_caster
->getLevel() - 60;
2758 level_diff
= m_caster
->getLevel() - 60;
2766 damage
-= multiplier
* level_diff
;
2771 if(unitTarget
->GetMaxPower(power
) == 0)
2774 unitTarget
->ModifyPower(power
,damage
);
2775 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2777 // Mad Alchemist's Potion
2778 if (m_spellInfo
->Id
== 45051)
2780 // find elixirs on target
2781 uint32 elixir_mask
= 0;
2782 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2783 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2785 uint32 spell_id
= itr
->second
->GetId();
2786 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2787 elixir_mask
|= mask
;
2790 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2791 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2793 // get all available elixirs by mask and spell level
2794 std::vector
<uint32
> elixirs
;
2795 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2796 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2798 if (itr
->second
& elixir_mask
)
2800 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2803 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2804 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2807 elixirs
.push_back(itr
->first
);
2811 if (!elixirs
.empty())
2813 // cast random elixir on target
2814 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2815 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2820 void Spell::EffectEnergisePct(uint32 i
)
2824 if(!unitTarget
->isAlive())
2827 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2830 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2832 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2836 uint32 gain
= damage
* maxPower
/ 100;
2837 unitTarget
->ModifyPower(power
, gain
);
2838 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2841 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2843 Player
* player
= (Player
*)m_caster
;
2849 if (Script
->GOHello(player
, gameObjTarget
))
2852 switch (gameObjTarget
->GetGoType())
2854 case GAMEOBJECT_TYPE_DOOR
:
2855 case GAMEOBJECT_TYPE_BUTTON
:
2856 gameObjTarget
->UseDoorOrButton();
2857 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2860 case GAMEOBJECT_TYPE_QUESTGIVER
:
2861 // start or end quest
2862 player
->PrepareQuestMenu(guid
);
2863 player
->SendPreparedQuest(guid
);
2866 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2867 // triggering linked GO
2868 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2869 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2872 case GAMEOBJECT_TYPE_GOOBER
:
2873 // goober_scripts can be triggered if the player don't have the quest
2874 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2876 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2877 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2880 // cast goober spell
2881 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2882 ///Quest require to be active for GO using
2883 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2886 gameObjTarget
->AddUniqueUse(player
);
2887 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2889 //TODO? Objective counting called without spell check but with quest objective check
2890 // if send spell id then this line will duplicate to spell casting call (double counting)
2891 // So we or have this line and not required in quest_template have reqSpellIdN
2892 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2893 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2895 // triggering linked GO
2896 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2897 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2901 case GAMEOBJECT_TYPE_CHEST
:
2902 // TODO: possible must be moved to loot release (in different from linked triggering)
2903 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2905 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2906 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2909 // triggering linked GO
2910 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2911 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2913 // Don't return, let loots been taken
2918 player
->SendLoot(guid
, loottype
);
2921 void Spell::EffectOpenLock(uint32 effIndex
)
2923 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2925 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2929 Player
* player
= (Player
*)m_caster
;
2937 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2938 // Arathi Basin banner opening !
2939 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2940 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2942 //CanUseBattleGroundObject() already called in CheckCast()
2943 // in battleground check
2944 if(BattleGround
*bg
= player
->GetBattleGround())
2946 // check if it's correct bg
2947 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2948 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2952 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2954 //CanUseBattleGroundObject() already called in CheckCast()
2955 // in battleground check
2956 if(BattleGround
*bg
= player
->GetBattleGround())
2958 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2959 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2963 lockId
= gameObjTarget
->GetLockId();
2964 guid
= gameObjTarget
->GetGUID();
2968 lockId
= itemTarget
->GetProto()->LockID
;
2969 guid
= itemTarget
->GetGUID();
2973 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2977 SkillType skillId
= SKILL_NONE
;
2978 int32 reqSkillValue
= 0;
2981 SpellCastResult res
= CanOpenLock(effIndex
,lockId
,skillId
,reqSkillValue
,skillValue
);
2982 if(res
!= SPELL_CAST_OK
)
2984 SendCastResult(res
);
2988 SendLoot(guid
, LOOT_SKINNING
);
2990 // not allow use skill grow at item base open
2991 if(!m_CastItem
&& skillId
!= SKILL_NONE
)
2993 // update skill if really known
2994 if(uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
2998 // Allow one skill-up until respawned
2999 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3000 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
) )
3001 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3006 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3012 void Spell::EffectSummonChangeItem(uint32 i
)
3014 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3017 Player
*player
= (Player
*)m_caster
;
3019 // applied only to using item
3023 // ... only to item in own inventory/bank/equip_slot
3024 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3027 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3031 uint16 pos
= m_CastItem
->GetPos();
3033 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3037 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3039 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3040 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3043 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3045 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3046 player
->DurabilityLoss(pNewItem
, loosePercent
);
3049 if( player
->IsInventoryPos( pos
) )
3051 ItemPosCountVec dest
;
3052 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3053 if( msg
== EQUIP_ERR_OK
)
3055 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3057 // prevent crash at access and unexpected charges counting with item update queue corrupt
3058 if(m_CastItem
==m_targets
.getItemTarget())
3059 m_targets
.setItemTarget(NULL
);
3063 player
->StoreItem( dest
, pNewItem
, true);
3067 else if( player
->IsBankPos ( pos
) )
3069 ItemPosCountVec dest
;
3070 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3071 if( msg
== EQUIP_ERR_OK
)
3073 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3075 // prevent crash at access and unexpected charges counting with item update queue corrupt
3076 if(m_CastItem
==m_targets
.getItemTarget())
3077 m_targets
.setItemTarget(NULL
);
3081 player
->BankItem( dest
, pNewItem
, true);
3085 else if( player
->IsEquipmentPos ( pos
) )
3088 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3089 if( msg
== EQUIP_ERR_OK
)
3091 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3093 // prevent crash at access and unexpected charges counting with item update queue corrupt
3094 if(m_CastItem
==m_targets
.getItemTarget())
3095 m_targets
.setItemTarget(NULL
);
3099 player
->EquipItem( dest
, pNewItem
, true);
3100 player
->AutoUnequipOffhandIfNeed();
3109 void Spell::EffectOpenSecretSafe(uint32 i
)
3111 EffectOpenLock(i
); //no difference for now
3114 void Spell::EffectProficiency(uint32
/*i*/)
3116 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3118 Player
*p_target
= (Player
*)unitTarget
;
3120 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3121 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3123 p_target
->AddWeaponProficiency(subClassMask
);
3124 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3126 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3128 p_target
->AddArmorProficiency(subClassMask
);
3129 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3133 void Spell::EffectApplyAreaAura(uint32 i
)
3137 if(!unitTarget
->isAlive())
3140 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3141 unitTarget
->AddAura(Aur
);
3144 void Spell::EffectSummonType(uint32 i
)
3146 switch(m_spellInfo
->EffectMiscValueB
[i
])
3148 case SUMMON_TYPE_GUARDIAN
:
3149 case SUMMON_TYPE_POSESSED
:
3150 case SUMMON_TYPE_POSESSED2
:
3151 case SUMMON_TYPE_FORCE_OF_NATURE
:
3152 case SUMMON_TYPE_GUARDIAN2
:
3153 EffectSummonGuardian(i
);
3155 case SUMMON_TYPE_WILD
:
3156 EffectSummonWild(i
);
3158 case SUMMON_TYPE_DEMON
:
3159 EffectSummonDemon(i
);
3161 case SUMMON_TYPE_SUMMON
:
3164 case SUMMON_TYPE_CRITTER
:
3165 case SUMMON_TYPE_CRITTER2
:
3166 case SUMMON_TYPE_CRITTER3
:
3167 EffectSummonCritter(i
);
3169 case SUMMON_TYPE_TOTEM_SLOT1
:
3170 case SUMMON_TYPE_TOTEM_SLOT2
:
3171 case SUMMON_TYPE_TOTEM_SLOT3
:
3172 case SUMMON_TYPE_TOTEM_SLOT4
:
3173 case SUMMON_TYPE_TOTEM
:
3174 EffectSummonTotem(i
);
3176 case SUMMON_TYPE_UNKNOWN1
:
3177 case SUMMON_TYPE_UNKNOWN2
:
3178 case SUMMON_TYPE_UNKNOWN3
:
3179 case SUMMON_TYPE_UNKNOWN4
:
3180 case SUMMON_TYPE_UNKNOWN5
:
3183 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3188 void Spell::EffectSummon(uint32 i
)
3190 if(m_caster
->GetPetGUID())
3195 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3198 uint32 level
= m_caster
->getLevel();
3199 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3201 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3203 // set timer for unsummon
3204 int32 duration
= GetSpellDuration(m_spellInfo
);
3206 spawnCreature
->SetDuration(duration
);
3211 Map
*map
= m_caster
->GetMap();
3212 uint32 pet_number
= objmgr
.GeneratePetNumber();
3213 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_caster
->GetPhaseMask(),
3214 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3216 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3217 delete spawnCreature
;
3221 // Summon in dest location
3223 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3225 x
= m_targets
.m_destX
;
3226 y
= m_targets
.m_destY
;
3227 z
= m_targets
.m_destZ
;
3230 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3232 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3234 if(!spawnCreature
->IsPositionValid())
3236 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3237 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3238 delete spawnCreature
;
3242 // set timer for unsummon
3243 int32 duration
= GetSpellDuration(m_spellInfo
);
3245 spawnCreature
->SetDuration(duration
);
3247 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3248 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3249 spawnCreature
->setPowerType(POWER_MANA
);
3250 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3251 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3252 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3253 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3254 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3255 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3256 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3257 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3258 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3260 spawnCreature
->InitStatsForLevel(level
);
3262 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3264 spawnCreature
->AIM_Initialize();
3265 spawnCreature
->InitPetCreateSpells();
3266 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3267 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3269 std::string name
= m_caster
->GetName();
3270 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3271 spawnCreature
->SetName( name
);
3273 map
->Add((Creature
*)spawnCreature
);
3275 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3277 m_caster
->SetPet(spawnCreature
);
3278 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3279 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3280 ((Player
*)m_caster
)->PetSpellInitialize();
3284 void Spell::EffectLearnSpell(uint32 i
)
3289 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3291 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3292 EffectLearnPetSpell(i
);
3297 Player
*player
= (Player
*)unitTarget
;
3299 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3300 player
->learnSpell(spellToLearn
,false);
3302 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3305 void Spell::EffectDispel(uint32 i
)
3310 // Fill possible dispell list
3311 std::vector
<Aura
*> dispel_list
;
3313 // Create dispel mask by dispel type
3314 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3315 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3316 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3317 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3319 Aura
*aur
= (*itr
).second
;
3320 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3322 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3324 bool positive
= true;
3325 if (!aur
->IsPositive())
3328 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3330 // do not remove positive auras if friendly target
3331 // negative auras if non-friendly target
3332 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3335 // Add aura to dispel list
3336 dispel_list
.push_back(aur
);
3339 // Ok if exist some buffs for dispel try dispel it
3340 if (!dispel_list
.empty())
3342 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3343 std::list
< uint32
> fail_list
; // spell_id
3344 int32 list_size
= dispel_list
.size();
3345 // Dispell N = damage buffs (or while exist buffs for dispel)
3346 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3348 // Random select buff for dispel
3349 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3351 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3352 // Base dispel chance
3353 // TODO: possible chance depend from spell level??
3354 int32 miss_chance
= 0;
3355 // Apply dispel mod from aura caster
3356 if (Unit
*caster
= aur
->GetCaster())
3358 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3359 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3362 if (roll_chance_i(miss_chance
))
3363 fail_list
.push_back(aur
->GetId());
3365 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3366 // Remove buff from list for prevent doubles
3367 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3369 Aura
*dispeled
= *j
;
3370 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3372 j
= dispel_list
.erase(j
);
3379 // Send success log and really remove auras
3380 if (!success_list
.empty())
3382 int32 count
= success_list
.size();
3383 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3384 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3385 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3386 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3387 data
<< uint8(0); // not used
3388 data
<< uint32(count
); // count
3389 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3391 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3392 data
<< uint32(spellInfo
->Id
); // Spell Id
3393 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3394 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3396 m_caster
->SendMessageToSet(&data
, true);
3400 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3402 uint32 heal_spell
= 0;
3403 switch (m_spellInfo
->Id
)
3405 case 19505: heal_spell
= 19658; break;
3406 case 19731: heal_spell
= 19732; break;
3407 case 19734: heal_spell
= 19733; break;
3408 case 19736: heal_spell
= 19735; break;
3409 case 27276: heal_spell
= 27278; break;
3410 case 27277: heal_spell
= 27279; break;
3412 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3416 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3419 // Send fail log to client
3420 if (!fail_list
.empty())
3422 // Failed to dispell
3423 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3424 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3425 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3426 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3427 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3428 data
<< uint32(*j
); // Spell Id
3429 m_caster
->SendMessageToSet(&data
, true);
3434 void Spell::EffectDualWield(uint32
/*i*/)
3436 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3437 ((Player
*)unitTarget
)->SetCanDualWield(true);
3440 void Spell::EffectPull(uint32
/*i*/)
3442 // TODO: create a proper pull towards distract spell center for distract
3443 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3446 void Spell::EffectDistract(uint32
/*i*/)
3448 // Check for possible target
3449 if (!unitTarget
|| unitTarget
->isInCombat())
3452 // target must be OK to do this
3453 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3456 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3458 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3460 // For players just turn them
3462 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3463 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3464 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3468 // Set creature Distracted, Stop it, And turn it
3469 unitTarget
->SetOrientation(angle
);
3470 unitTarget
->StopMoving();
3471 unitTarget
->GetMotionMaster()->MoveDistract(damage
*IN_MILISECONDS
);
3475 void Spell::EffectPickPocket(uint32
/*i*/)
3477 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3480 // victim must be creature and attackable
3481 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3484 // victim have to be alive and humanoid or undead
3485 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3487 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3489 if (chance
> irand(0, 19))
3491 // Stealing successful
3492 //sLog.outDebug("Sending loot from pickpocket");
3493 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3497 // Reveal action + get attack
3498 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3499 if (((Creature
*)unitTarget
)->AI())
3500 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3505 void Spell::EffectAddFarsight(uint32 i
)
3507 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3508 int32 duration
= GetSpellDuration(m_spellInfo
);
3509 DynamicObject
* dynObj
= new DynamicObject
;
3510 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
))
3515 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3516 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3517 m_caster
->AddDynObject(dynObj
);
3518 dynObj
->GetMap()->Add(dynObj
);
3519 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3520 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3523 void Spell::EffectSummonWild(uint32 i
)
3525 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3529 uint32 level
= m_caster
->getLevel();
3531 // level of creature summoned using engineering item based at engineering skill level
3532 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3534 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3535 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3537 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3545 // select center of summon position
3546 float center_x
= m_targets
.m_destX
;
3547 float center_y
= m_targets
.m_destY
;
3548 float center_z
= m_targets
.m_destZ
;
3550 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3552 int32 amount
= damage
> 0 ? damage
: 1;
3554 for(int32 count
= 0; count
< amount
; ++count
)
3557 // If dest location if present
3558 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3560 // Summon 1 unit in dest location
3563 px
= m_targets
.m_destX
;
3564 py
= m_targets
.m_destY
;
3565 pz
= m_targets
.m_destZ
;
3567 // Summon in random point all other units if location present
3569 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3571 // Summon if dest location not present near caster
3573 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3575 int32 duration
= GetSpellDuration(m_spellInfo
);
3577 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3579 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3583 void Spell::EffectSummonGuardian(uint32 i
)
3585 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3589 // Jewelery statue case (totem like)
3590 if(m_spellInfo
->SpellIconID
==2056)
3592 EffectSummonTotem(i
);
3596 // set timer for unsummon
3597 int32 duration
= GetSpellDuration(m_spellInfo
);
3599 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3600 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3601 // so this code hack in fact
3602 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3603 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3604 return; // find old guardian, ignore summon
3606 // in another case summon new
3607 uint32 level
= m_caster
->getLevel();
3609 // level of pet summoned using engineering item based at engineering skill level
3610 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3612 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3613 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3615 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3623 // select center of summon position
3624 float center_x
= m_targets
.m_destX
;
3625 float center_y
= m_targets
.m_destY
;
3626 float center_z
= m_targets
.m_destZ
;
3628 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3630 int32 amount
= damage
> 0 ? damage
: 1;
3632 for(int32 count
= 0; count
< amount
; ++count
)
3634 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3636 Map
*map
= m_caster
->GetMap();
3637 uint32 pet_number
= objmgr
.GeneratePetNumber();
3638 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3639 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3641 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3642 delete spawnCreature
;
3647 // If dest location if present
3648 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3650 // Summon 1 unit in dest location
3653 px
= m_targets
.m_destX
;
3654 py
= m_targets
.m_destY
;
3655 pz
= m_targets
.m_destZ
;
3657 // Summon in random point all other units if location present
3659 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3661 // Summon if dest location not present near caster
3663 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3665 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3667 if(!spawnCreature
->IsPositionValid())
3669 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3670 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3671 delete spawnCreature
;
3676 spawnCreature
->SetDuration(duration
);
3678 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3679 spawnCreature
->setPowerType(POWER_MANA
);
3680 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3681 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3682 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3683 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3684 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3685 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3686 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3688 spawnCreature
->InitStatsForLevel(level
);
3689 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3691 spawnCreature
->AIM_Initialize();
3693 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3694 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3696 map
->Add((Creature
*)spawnCreature
);
3700 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3705 if(unitTarget
->isInFlight())
3708 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3711 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3713 unitTarget
->NearTeleportTo(fx
,fy
,fz
,-m_caster
->GetOrientation(),unitTarget
==m_caster
);
3716 void Spell::EffectLearnSkill(uint32 i
)
3718 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3724 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3725 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3726 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3729 void Spell::EffectAddHonor(uint32
/*i*/)
3731 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3734 // not scale value for item based reward (/10 value expected)
3737 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/10);
3738 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo
->Id
, damage
/10, m_CastItem
->GetEntry(),((Player
*)unitTarget
)->GetGUIDLow());
3742 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3745 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
3746 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
3747 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
3751 //maybe we have correct honor_gain in damage already
3752 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3753 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3757 void Spell::EffectTradeSkill(uint32
/*i*/)
3759 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3761 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3762 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3763 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3766 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3768 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3773 Player
* p_caster
= (Player
*)m_caster
;
3775 // not grow at item use at item case
3776 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3778 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3782 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3786 // item can be in trade slot and have owner diff. from caster
3787 Player
* item_owner
= itemTarget
->GetOwner();
3791 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3793 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3794 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3795 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3796 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3799 // remove old enchanting before applying new if equipped
3800 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3802 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3804 // add new enchanting if equipped
3805 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3808 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3810 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3815 Player
* p_caster
= (Player
*)m_caster
;
3817 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3821 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3825 // support only enchantings with add socket in this slot
3827 bool add_socket
= false;
3828 for(int i
= 0; i
< 3; ++i
)
3830 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3838 sLog
.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (u), not suppoted yet.",
3839 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3844 // item can be in trade slot and have owner diff. from caster
3845 Player
* item_owner
= itemTarget
->GetOwner();
3849 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3851 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3852 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3853 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3854 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3857 // remove old enchanting before applying new if equipped
3858 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3860 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3862 // add new enchanting if equipped
3863 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3866 void Spell::EffectEnchantItemTmp(uint32 i
)
3868 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3871 Player
* p_caster
= (Player
*)m_caster
;
3876 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3878 // Shaman Rockbiter Weapon
3879 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3881 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3883 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3884 // with already applied percent bonus from Elemental Weapons talent
3885 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3886 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3887 switch(enchnting_damage
)
3890 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3892 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3893 case 5: enchant_id
= 3025; break; // 20%
3895 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3896 case 7: enchant_id
= 3027; break; // 20%
3898 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3899 case 10: enchant_id
= 503; break; // 14%
3900 case 11: enchant_id
= 3031; break; // 20%
3902 case 15: enchant_id
= 3035; break; // 0%
3903 case 16: enchant_id
= 1663; break; // 7%
3904 case 17: enchant_id
= 3033; break; // 14%
3905 case 18: enchant_id
= 3034; break; // 20%
3907 case 28: enchant_id
= 3038; break; // 0%
3908 case 29: enchant_id
= 683; break; // 7%
3909 case 31: enchant_id
= 3036; break; // 14%
3910 case 33: enchant_id
= 3037; break; // 20%
3912 case 40: enchant_id
= 3041; break; // 0%
3913 case 42: enchant_id
= 1664; break; // 7%
3914 case 45: enchant_id
= 3039; break; // 14%
3915 case 48: enchant_id
= 3040; break; // 20%
3917 case 49: enchant_id
= 3044; break; // 0%
3918 case 52: enchant_id
= 2632; break; // 7%
3919 case 55: enchant_id
= 3042; break; // 14%
3920 case 58: enchant_id
= 3043; break; // 20%
3922 case 62: enchant_id
= 2633; break; // 0%
3923 case 66: enchant_id
= 3018; break; // 7%
3924 case 70: enchant_id
= 3019; break; // 14%
3925 case 74: enchant_id
= 3020; break; // 20%
3927 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3934 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3938 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3941 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3945 // select enchantment duration
3948 // rogue family enchantments exception by duration
3949 if(m_spellInfo
->Id
==38615)
3950 duration
= 1800; // 30 mins
3951 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3952 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3953 duration
= 3600; // 1 hour
3954 // shaman family enchantments
3955 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3956 duration
= 1800; // 30 mins
3957 // other cases with this SpellVisual already selected
3958 else if(m_spellInfo
->SpellVisual
[0]==215)
3959 duration
= 1800; // 30 mins
3960 // some fishing pole bonuses
3961 else if(m_spellInfo
->SpellVisual
[0]==563)
3962 duration
= 600; // 10 mins
3963 // shaman rockbiter enchantments
3964 else if(m_spellInfo
->SpellVisual
[0]==0)
3965 duration
= 1800; // 30 mins
3966 else if(m_spellInfo
->Id
==29702)
3967 duration
= 300; // 5 mins
3968 else if(m_spellInfo
->Id
==37360)
3969 duration
= 300; // 5 mins
3972 duration
= 3600; // 1 hour
3974 // item can be in trade slot and have owner diff. from caster
3975 Player
* item_owner
= itemTarget
->GetOwner();
3979 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3981 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3982 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3983 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3984 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3987 // remove old enchanting before applying new if equipped
3988 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3990 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3992 // add new enchanting if equipped
3993 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3996 void Spell::EffectTameCreature(uint32
/*i*/)
3998 if(m_caster
->GetPetGUID())
4004 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4007 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4009 if(creatureTarget
->isPet())
4012 if(m_caster
->getClass() != CLASS_HUNTER
)
4015 // cast finish successfully
4016 //SendChannelUpdate(0);
4019 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4021 // kill original creature
4022 creatureTarget
->setDeathState(JUST_DIED
);
4023 creatureTarget
->RemoveCorpse();
4024 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4026 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4028 // prepare visual effect for levelup
4029 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4032 pet
->GetMap()->Add((Creature
*)pet
);
4034 // visual effect for levelup
4035 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4037 // caster have pet now
4038 m_caster
->SetPet(pet
);
4040 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4042 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4043 ((Player
*)m_caster
)->PetSpellInitialize();
4047 void Spell::EffectSummonPet(uint32 i
)
4049 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4051 Pet
*OldSummon
= m_caster
->GetPet();
4053 // if pet requested type already exist
4056 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4058 // pet in corpse state can't be summoned
4059 if( OldSummon
->isDead() )
4062 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4063 OldSummon
->SetMapId(m_caster
->GetMapId());
4066 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4068 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4069 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4071 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4073 ((Player
*)m_caster
)->PetSpellInitialize();
4078 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4079 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4084 Pet
* NewSummon
= new Pet
;
4086 // petentry==0 for hunter "call pet" (current pet summoned if any)
4087 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4089 if(NewSummon
->getPetType()==SUMMON_PET
)
4091 // Remove Demonic Sacrifice auras (known pet)
4092 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4093 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4095 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4097 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4098 itr
= auraClassScripts
.begin();
4108 // not error in case fail hunter call pet
4115 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4119 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4124 Map
*map
= m_caster
->GetMap();
4125 uint32 pet_number
= objmgr
.GeneratePetNumber();
4126 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4127 petentry
, pet_number
))
4134 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4136 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4138 if(!NewSummon
->IsPositionValid())
4140 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4141 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4146 uint32 petlevel
= m_caster
->getLevel();
4147 NewSummon
->setPetType(SUMMON_PET
);
4149 uint32 faction
= m_caster
->getFaction();
4150 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4152 if ( ((Creature
*)m_caster
)->isTotem() )
4153 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4155 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4158 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4159 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4160 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4161 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4162 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4163 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4164 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4165 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4166 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4167 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4169 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4170 // this enables pet details window (Shift+P)
4172 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4173 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4174 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4176 NewSummon
->InitStatsForLevel(petlevel
);
4177 NewSummon
->InitPetCreateSpells();
4178 NewSummon
->InitTalentForLevel();
4180 if(NewSummon
->getPetType()==SUMMON_PET
)
4182 // Remove Demonic Sacrifice auras (new pet)
4183 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4184 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4186 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4188 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4189 itr
= auraClassScripts
.begin();
4195 // generate new name for summon pet
4196 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4197 if(!new_name
.empty())
4198 NewSummon
->SetName(new_name
);
4200 else if(NewSummon
->getPetType()==HUNTER_PET
)
4201 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4203 NewSummon
->AIM_Initialize();
4204 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4205 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4207 map
->Add((Creature
*)NewSummon
);
4209 m_caster
->SetPet(NewSummon
);
4210 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4212 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4214 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4215 ((Player
*)m_caster
)->PetSpellInitialize();
4219 void Spell::EffectLearnPetSpell(uint32 i
)
4221 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4224 Player
*_player
= (Player
*)m_caster
;
4226 Pet
*pet
= _player
->GetPet();
4232 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4233 if(!learn_spellproto
)
4236 pet
->learnSpell(learn_spellproto
->Id
);
4238 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4239 _player
->PetSpellInitialize();
4242 void Spell::EffectTaunt(uint32
/*i*/)
4244 // this effect use before aura Taunt apply for prevent taunt already attacking target
4245 // for spell as marked "non effective at already attacking target"
4246 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4248 if(unitTarget
->getVictim()==m_caster
)
4250 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4255 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4256 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4257 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4260 void Spell::EffectWeaponDmg(uint32 i
)
4264 if(!unitTarget
->isAlive())
4267 // multiple weapon dmg effect workaround
4268 // execute only the last weapon damage
4269 // and handle all effects at once
4270 for (int j
= 0; j
< 3; j
++)
4272 switch(m_spellInfo
->Effect
[j
])
4274 case SPELL_EFFECT_WEAPON_DAMAGE
:
4275 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4276 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4277 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4278 if (j
< i
) // we must calculate only at last weapon effect
4284 // some spell specific modifiers
4285 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4287 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4288 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4289 bool normalized
= false;
4291 int32 spell_bonus
= 0; // bonus specific for spell
4292 switch(m_spellInfo
->SpellFamilyName
)
4294 case SPELLFAMILY_WARRIOR
:
4296 // Whirlwind, single only spell with 2 weapon white damage apply if have
4297 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4299 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4300 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4302 // Devastate bonus and sunder armor refresh
4303 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4306 // Need refresh all Sunder Armor auras from this caster
4307 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4308 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4310 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4311 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4312 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4313 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4315 (*itr
).second
->RefreshAura();
4316 stack
= (*itr
).second
->GetStackAmount();
4320 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4324 case SPELLFAMILY_ROGUE
:
4326 // Mutilate (for each hand)
4327 if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4331 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4336 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4337 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4339 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4348 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4352 case SPELLFAMILY_PALADIN
:
4354 // Seal of Command - receive benefit from Spell Damage and Healing
4355 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4357 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4358 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4359 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4363 case SPELLFAMILY_SHAMAN
:
4365 // Skyshatter Harness item set bonus
4367 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4369 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4370 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4372 // Stormstrike AP Buff
4373 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4375 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4383 int32 fixed_bonus
= 0;
4384 for (int j
= 0; j
< 3; j
++)
4386 switch(m_spellInfo
->Effect
[j
])
4388 case SPELL_EFFECT_WEAPON_DAMAGE
:
4389 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4390 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4392 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4393 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4396 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4397 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4399 // applied only to prev.effects fixed damage
4400 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4403 break; // not weapon damage effect, just skip
4407 // apply weaponDamagePercentMod to spell bonus also
4408 if(spellBonusNeedWeaponDamagePercentMod
)
4409 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4411 // non-weapon damage
4412 int32 bonus
= spell_bonus
+ fixed_bonus
;
4414 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4418 switch(m_attackType
)
4421 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4422 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4423 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4426 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4427 bonus
= int32(bonus
*weapon_total_pct
);
4430 // + weapon damage with applied weapon% dmg to base weapon damage in call
4431 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4434 bonus
= int32(bonus
*totalDamagePercentMod
);
4436 // prevent negative damage
4437 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4439 // Add melee damage bonuses (also check for negative)
4440 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4441 m_damage
+= eff_damage
;
4444 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4446 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4447 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4451 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4453 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4454 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4458 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4460 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4462 // wands don't have ammo
4463 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4466 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4468 if(pItem
->GetMaxStackCount()==1)
4470 // decrease durability for non-stackable throw weapon
4471 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4475 // decrease items amount for stackable throw weapon
4477 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4480 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4481 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4485 void Spell::EffectThreat(uint32
/*i*/)
4487 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4490 if(!unitTarget
->CanHaveThreatList())
4493 unitTarget
->AddThreat(m_caster
, float(damage
));
4496 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4500 if(!unitTarget
->isAlive())
4503 uint32 heal
= m_caster
->GetMaxHealth();
4508 void Spell::EffectInterruptCast(uint32
/*i*/)
4512 if(!unitTarget
->isAlive())
4515 // TODO: not all spells that used this effect apply cooldown at school spells
4516 // also exist case: apply cooldown to interrupted cast only and to all spells
4517 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4519 if (unitTarget
->m_currentSpells
[i
])
4521 // check if we can interrupt spell
4522 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4524 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4525 unitTarget
->InterruptSpell(i
,false);
4531 void Spell::EffectSummonObjectWild(uint32 i
)
4533 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4535 GameObject
* pGameObj
= new GameObject
;
4537 WorldObject
* target
= focusObject
;
4542 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4544 x
= m_targets
.m_destX
;
4545 y
= m_targets
.m_destY
;
4546 z
= m_targets
.m_destZ
;
4549 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4551 Map
*map
= target
->GetMap();
4553 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4554 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4560 int32 duration
= GetSpellDuration(m_spellInfo
);
4561 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4562 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4564 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4565 m_caster
->AddGameObject(pGameObj
);
4568 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4570 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4572 Player
*pl
= (Player
*)m_caster
;
4573 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4574 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4576 uint32 team
= ALLIANCE
;
4578 if(pl
->GetTeam() == team
)
4581 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4586 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4588 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4590 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4591 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4593 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4598 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4600 GameObject
* linkedGO
= new GameObject
;
4601 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4602 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4604 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4605 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4607 m_caster
->AddGameObject(linkedGO
);
4619 void Spell::EffectScriptEffect(uint32 effIndex
)
4621 // TODO: we must implement hunter pet summon at login there (spell 6962)
4623 switch(m_spellInfo
->SpellFamilyName
)
4625 case SPELLFAMILY_GENERIC
:
4627 switch(m_spellInfo
->Id
)
4629 // PX-238 Winter Wondervolt TRAP
4632 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4635 for(int j
= 0; j
< 4; ++j
)
4636 if(unitTarget
->HasAura(spells
[j
],0))
4640 uint32 iTmpSpellId
= spells
[urand(0,3)];
4643 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4649 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4652 uint32 spell_id
= 0;
4655 case 1: spell_id
= 8854; break;
4656 default: spell_id
= 8855; break;
4659 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4662 // Brittle Armor - need remove one 24575 Brittle Armor aura
4664 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4666 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4668 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4670 // Orb teleport spells
4684 switch(m_spellInfo
->Id
)
4686 case 25140: spellid
= 32571; break;
4687 case 25143: spellid
= 32572; break;
4688 case 25650: spellid
= 30140; break;
4689 case 25652: spellid
= 30141; break;
4690 case 29128: spellid
= 32568; break;
4691 case 29129: spellid
= 32569; break;
4692 case 35376: spellid
= 25649; break;
4693 case 35727: spellid
= 35730; break;
4698 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4701 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4716 if(!unitTarget
|| !unitTarget
->isAlive())
4719 // Onyxia Scale Cloak
4720 if(unitTarget
->GetDummyAura(22683))
4724 m_caster
->CastSpell(unitTarget
, 22682, true);
4727 // Summon Black Qiraji Battle Tank
4733 // Prevent stacking of mounts
4734 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4736 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4737 if (unitTarget
->GetAreaId() == 3428)
4738 unitTarget
->CastSpell(unitTarget
, 25863, false);
4740 unitTarget
->CastSpell(unitTarget
, 26655, false);
4743 // Piccolo of the Flaming Fire
4746 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4748 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4754 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4755 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4758 // Mirren's Drinking Hat
4762 switch ( urand(1,6) )
4764 case 1:case 2:case 3:
4765 item
= 23584;break; // Loch Modan Lager
4767 item
= 23585;break; // Stouthammer Lite
4769 item
= 23586;break; // Aerie Peak Pale Ale
4772 DoCreateItem(effIndex
,item
);
4778 // Removes snares and roots.
4779 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4780 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4781 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4785 Aura
*aur
= iter
->second
;
4786 if (!aur
->IsPositive()) //only remove negative spells
4788 // check for mechanic mask
4789 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4791 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4795 next
= Auras
.begin();
4807 unitTarget
->CastSpell(unitTarget
, 41131, true);
4810 // Force Cast - Portal Effect: Sunwell Isle
4816 unitTarget
->CastSpell(unitTarget
, 44870, true);
4819 // Goblin Weather Machine
4828 case 0: spellId
= 46740; break;
4829 case 1: spellId
= 46739; break;
4830 case 2: spellId
= 46738; break;
4831 case 3: spellId
= 46736; break;
4833 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4839 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4842 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4846 // Emblazon Runeblade
4852 unitTarget
->CastSpell(unitTarget
,51771,false);
4858 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4860 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4861 unitTarget
->CastSpell(unitTarget
, damage
, false);
4864 case 58418: // Portal to Orgrimmar
4865 case 58420: // Portal to Stormwind
4867 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
4870 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
4871 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
4873 if( ((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
) )
4874 unitTarget
->CastSpell(unitTarget
, spellID
, true);
4878 // random spell learn instead placeholder
4879 case 60893: // Northrend Alchemy Research
4880 case 61177: // Northrend Inscription Research
4881 case 61288: // Minor Inscription Research
4882 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4884 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4886 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4890 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4892 Player
* player
= (Player
*)m_caster
;
4894 // need replace effect 0 item by loot
4895 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4897 if(!player
->HasItemCount(reagent_id
,1))
4902 player
->DestroyItemCount (reagent_id
,count
,true);
4904 // create some random items
4905 player
->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
4907 // learn random explicit discovery recipe (if any)
4908 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4909 player
->learnSpell(discoveredSpell
,false);
4915 case SPELLFAMILY_WARLOCK
:
4917 switch(m_spellInfo
->Id
)
4919 // Healthstone creating spells
4931 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4932 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4934 if((*i
)->GetId() == 18692)
4939 else if((*i
)->GetId() == 18693)
4946 static uint32
const itypes
[8][3] = {
4947 { 5512,19004,19005}, // Minor Healthstone
4948 { 5511,19006,19007}, // Lesser Healthstone
4949 { 5509,19008,19009}, // Healthstone
4950 { 5510,19010,19011}, // Greater Healthstone
4951 { 9421,19012,19013}, // Major Healthstone
4952 {22103,22104,22105}, // Master Healthstone
4953 {36889,36890,36891}, // Demonic Healthstone
4954 {36892,36893,36894} // Fel Healthstone
4957 switch(m_spellInfo
->Id
)
4960 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4962 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4964 itemtype
=itypes
[2][rank
];break; // Healthstone
4966 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4968 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4970 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4972 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4974 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4978 DoCreateItem( effIndex
, itemtype
);
4984 case SPELLFAMILY_PRIEST
:
4986 switch(m_spellInfo
->Id
)
4988 // Pain and Suffering
4993 // Refresh Shadow Word: Pain on target
4994 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
4995 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
4997 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4998 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
4999 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
5000 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5002 (*itr
).second
->RefreshAura();
5013 case SPELLFAMILY_HUNTER
:
5015 switch(m_spellInfo
->Id
)
5021 int32 basePoint
= 0;
5022 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5023 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5025 Aura
*aura
= (*i
).second
;
5026 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5028 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5029 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5030 if (!(familyFlag
& 0x000000800000C000LL
))
5032 // Refresh aura duration
5033 aura
->RefreshAura();
5035 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5036 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5038 spellId
= 53353; // 53353 Chimera Shot - Serpent
5039 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5041 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5042 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5044 spellId
= 53358; // 53358 Chimera Shot - Viper
5045 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5047 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5048 if (familyFlag
& 0x0000000000008000LL
)
5049 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5050 // ?? nothing say in spell desc (possibly need addition check)
5051 //if (familyFlag & 0x0000010000000000LL || // dot
5052 // familyFlag & 0x0000100000000000LL) // stun
5054 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5058 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5066 case SPELLFAMILY_PALADIN
:
5069 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5071 if(!unitTarget
|| !unitTarget
->isAlive())
5073 uint32 spellId1
= 0;
5074 uint32 spellId2
= 0;
5076 // Judgement self add switch
5077 switch (m_spellInfo
->Id
)
5079 case 41467: break; // Judgement
5080 case 53407: spellId1
= 20184; break; // Judgement of Justice
5081 case 20271: // Judgement of Light
5082 case 57774: spellId1
= 20185; break; // Judgement of Light
5083 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5087 // all seals have aura dummy in 2 effect
5088 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5089 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5091 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5092 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5093 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5095 spellId2
= (*itr
)->GetModifier()->m_amount
;
5096 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5102 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5104 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5108 case SPELLFAMILY_POTION
:
5110 switch(m_spellInfo
->Id
)
5117 unitTarget
->CastSpell(unitTarget
, 28694, true);
5125 // 25% chance of casting a random buff
5126 if(roll_chance_i(75))
5129 // triggered spells are 28703 to 28707
5130 // Note: some sources say, that there was the possibility of
5131 // receiving a debuff. However, this seems to be removed by a patch.
5132 const uint32 spellid
= 28703;
5134 // don't overwrite an existing aura
5135 for(uint8 i
=0; i
<5; i
++)
5136 if(unitTarget
->HasAura(spellid
+i
, 0))
5138 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5147 // 25% chance of casting Nightmare Pollen
5148 if(roll_chance_i(75))
5150 unitTarget
->CastSpell(unitTarget
, 28721, true);
5158 // normal DB scripted effect
5162 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5163 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5166 void Spell::EffectSanctuary(uint32
/*i*/)
5170 //unitTarget->CombatStop();
5172 unitTarget
->CombatStop();
5173 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5174 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5175 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5177 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5181 void Spell::EffectAddComboPoints(uint32
/*i*/)
5186 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5192 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5195 void Spell::EffectDuel(uint32 i
)
5197 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5200 Player
*caster
= (Player
*)m_caster
;
5201 Player
*target
= (Player
*)unitTarget
;
5203 // caster or target already have requested duel
5204 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5207 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5208 // Don't have to check the target's map since you cannot challenge someone across maps
5209 uint32 mapid
= caster
->GetMapId();
5210 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5212 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5216 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5217 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5219 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5223 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5224 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5226 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5230 //CREATE DUEL FLAG OBJECT
5231 GameObject
* pGameObj
= new GameObject
;
5233 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5235 Map
*map
= m_caster
->GetMap();
5236 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5237 map
, m_caster
->GetPhaseMask(),
5238 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5239 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5240 m_caster
->GetPositionZ(),
5241 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5247 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5248 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5249 int32 duration
= GetSpellDuration(m_spellInfo
);
5250 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5251 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5253 m_caster
->AddGameObject(pGameObj
);
5258 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5259 data
<< pGameObj
->GetGUID();
5260 data
<< caster
->GetGUID();
5261 caster
->GetSession()->SendPacket(&data
);
5262 target
->GetSession()->SendPacket(&data
);
5265 DuelInfo
*duel
= new DuelInfo
;
5266 duel
->initiator
= caster
;
5267 duel
->opponent
= target
;
5268 duel
->startTime
= 0;
5269 duel
->startTimer
= 0;
5270 caster
->duel
= duel
;
5272 DuelInfo
*duel2
= new DuelInfo
;
5273 duel2
->initiator
= caster
;
5274 duel2
->opponent
= caster
;
5275 duel2
->startTime
= 0;
5276 duel2
->startTimer
= 0;
5277 target
->duel
= duel2
;
5279 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5280 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5283 void Spell::EffectStuck(uint32
/*i*/)
5285 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5288 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5291 Player
* pTarget
= (Player
*)unitTarget
;
5293 sLog
.outDebug("Spell Effect: Stuck");
5294 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());
5296 if(pTarget
->isInFlight())
5299 // homebind location is loaded always
5300 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5302 // Stuck spell trigger Hearthstone cooldown
5303 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5306 Spell
spell(pTarget
,spellInfo
,true,0);
5307 spell
.SendSpellCooldown();
5310 void Spell::EffectSummonPlayer(uint32
/*i*/)
5312 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5315 // Evil Twin (ignore player summon, but hide this for summoner)
5316 if(unitTarget
->GetDummyAura(23445))
5320 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5322 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5324 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5325 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5326 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5327 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5328 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5331 static ScriptInfo
generateActivateCommand()
5334 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5338 void Spell::EffectActivateObject(uint32 effect_idx
)
5343 static ScriptInfo activateCommand
= generateActivateCommand();
5345 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5347 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5350 void Spell::EffectApplyGlyph(uint32 i
)
5352 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5355 Player
*player
= (Player
*)m_caster
;
5358 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5360 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5362 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5364 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5366 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5367 return; // glyph slot mismatch
5372 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5374 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5376 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5377 player
->SetGlyph(m_glyphIndex
, 0);
5381 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5382 player
->SetGlyph(m_glyphIndex
, glyph
);
5387 void Spell::EffectSummonTotem(uint32 i
)
5390 switch(m_spellInfo
->EffectMiscValueB
[i
])
5392 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5393 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5394 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5395 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5396 // Battle standard case
5397 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5398 // jewelery statue case, like totem without slot
5399 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5403 if(slot
< MAX_TOTEM
)
5405 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5408 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5409 if(OldTotem
&& OldTotem
->isTotem())
5410 ((Totem
*)OldTotem
)->UnSummon();
5415 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5416 team
= ((Player
*)m_caster
)->GetTeam();
5418 Totem
* pTotem
= new Totem
;
5420 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5421 m_spellInfo
->EffectMiscValue
[i
], team
))
5427 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5430 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5432 // totem must be at same Z in case swimming caster and etc.
5433 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5434 z
= m_caster
->GetPositionZ();
5436 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5438 if(slot
< MAX_TOTEM
)
5439 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5441 pTotem
->SetOwner(m_caster
->GetGUID());
5442 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5444 int32 duration
=GetSpellDuration(m_spellInfo
);
5445 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5446 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5447 pTotem
->SetDuration(duration
);
5449 if (damage
) // if not spell info, DB values used
5451 pTotem
->SetMaxHealth(damage
);
5452 pTotem
->SetHealth(damage
);
5455 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5457 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5458 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5460 pTotem
->Summon(m_caster
);
5462 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5464 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5465 data
<< uint8(slot
);
5466 data
<< uint64(pTotem
->GetGUID());
5467 data
<< uint32(duration
);
5468 data
<< uint32(m_spellInfo
->Id
);
5469 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5473 void Spell::EffectEnchantHeldItem(uint32 i
)
5475 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5476 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5479 Player
* item_owner
= (Player
*)unitTarget
;
5480 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5486 if(!item
->IsEquipped())
5489 if (m_spellInfo
->EffectMiscValue
[i
])
5491 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5492 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5494 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5496 duration
= 10; //10 seconds for enchants which don't have listed duration
5498 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5502 // Always go to temp enchantment slot
5503 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5505 // Enchantment will not be applied if a different one already exists
5506 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5509 // Apply the temporary enchantment
5510 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
5511 item_owner
->ApplyEnchantment(item
,slot
,true);
5515 void Spell::EffectDisEnchant(uint32
/*i*/)
5517 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5520 Player
* p_caster
= (Player
*)m_caster
;
5521 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5524 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5526 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5528 // item will be removed at disenchanting end
5531 void Spell::EffectInebriate(uint32
/*i*/)
5533 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5536 Player
*player
= (Player
*)unitTarget
;
5537 uint16 currentDrunk
= player
->GetDrunkValue();
5538 uint16 drunkMod
= damage
* 256;
5539 if (currentDrunk
+ drunkMod
> 0xFFFF)
5540 currentDrunk
= 0xFFFF;
5542 currentDrunk
+= drunkMod
;
5543 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5546 void Spell::EffectFeedPet(uint32 i
)
5548 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5551 Player
*_player
= (Player
*)m_caster
;
5553 Item
* foodItem
= m_targets
.getItemTarget();
5557 Pet
*pet
= _player
->GetPet();
5564 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5569 _player
->DestroyItemCount(foodItem
,count
,true);
5570 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5572 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5575 void Spell::EffectDismissPet(uint32
/*i*/)
5577 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5580 Pet
* pet
= m_caster
->GetPet();
5582 // not let dismiss dead pet
5583 if(!pet
||!pet
->isAlive())
5586 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5589 void Spell::EffectSummonObject(uint32 i
)
5591 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5594 switch(m_spellInfo
->Effect
[i
])
5596 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5597 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5598 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5599 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5603 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5606 GameObject
* obj
= NULL
;
5608 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5610 if(obj
) obj
->Delete();
5611 m_caster
->m_ObjectSlot
[slot
] = 0;
5614 GameObject
* pGameObj
= new GameObject
;
5617 // If dest location if present
5618 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5620 x
= m_targets
.m_destX
;
5621 y
= m_targets
.m_destY
;
5622 z
= m_targets
.m_destZ
;
5624 // Summon in random point all other units if location present
5626 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5628 Map
*map
= m_caster
->GetMap();
5629 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5630 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5636 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5637 int32 duration
= GetSpellDuration(m_spellInfo
);
5638 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5639 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5640 m_caster
->AddGameObject(pGameObj
);
5643 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5644 data
<< pGameObj
->GetGUID();
5645 m_caster
->SendMessageToSet(&data
,true);
5647 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5650 void Spell::EffectResurrect(uint32
/*effIndex*/)
5654 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5657 if(unitTarget
->isAlive())
5659 if(!unitTarget
->IsInWorld())
5662 switch (m_spellInfo
->Id
)
5664 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5666 if (roll_chance_i(67))
5668 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5672 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5674 if (roll_chance_i(50))
5676 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5684 Player
* pTarget
= ((Player
*)unitTarget
);
5686 if(pTarget
->isRessurectRequested()) // already have one active request
5689 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5690 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5692 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5693 SendResurrectRequest(pTarget
);
5696 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5698 if(!unitTarget
|| !unitTarget
->isAlive())
5701 if( unitTarget
->m_extraAttacks
)
5704 unitTarget
->m_extraAttacks
= damage
;
5707 void Spell::EffectParry(uint32
/*i*/)
5709 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5710 ((Player
*)unitTarget
)->SetCanParry(true);
5713 void Spell::EffectBlock(uint32
/*i*/)
5715 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5716 ((Player
*)unitTarget
)->SetCanBlock(true);
5719 void Spell::EffectMomentMove(uint32 i
)
5721 if(unitTarget
->isInFlight())
5724 if( m_spellInfo
->rangeIndex
== 1) //self range
5726 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5730 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5732 unitTarget
->GetPosition(ox
,oy
,oz
);
5734 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5735 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5740 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5743 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(),unitTarget
==m_caster
);
5747 void Spell::EffectReputation(uint32 i
)
5749 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5752 Player
*_player
= (Player
*)unitTarget
;
5754 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5756 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5758 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5763 _player
->GetReputationMgr().ModifyReputation(factionEntry
,rep_change
);
5766 void Spell::EffectQuestComplete(uint32 i
)
5768 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5771 Player
*_player
= (Player
*)m_caster
;
5773 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5774 _player
->AreaExploredOrEventHappens(quest_id
);
5777 void Spell::EffectSelfResurrect(uint32 i
)
5779 if(!unitTarget
|| unitTarget
->isAlive())
5781 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5783 if(!unitTarget
->IsInWorld())
5792 health
= uint32(-damage
);
5793 mana
= m_spellInfo
->EffectMiscValue
[i
];
5798 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5799 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5800 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5803 Player
*plr
= ((Player
*)unitTarget
);
5804 plr
->ResurrectPlayer(0.0f
);
5806 plr
->SetHealth( health
);
5807 plr
->SetPower(POWER_MANA
, mana
);
5808 plr
->SetPower(POWER_RAGE
, 0 );
5809 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5811 plr
->SpawnCorpseBones();
5816 void Spell::EffectSkinning(uint32
/*i*/)
5818 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5820 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5823 Creature
* creature
= (Creature
*) unitTarget
;
5824 int32 targetLevel
= creature
->getLevel();
5826 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5828 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5829 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5831 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5833 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5835 // Double chances for elites
5836 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5839 void Spell::EffectCharge(uint32
/*i*/)
5841 if(!unitTarget
|| !m_caster
)
5845 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5846 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5847 ((Creature
*)unitTarget
)->StopMoving();
5849 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5850 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5852 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5853 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5855 // not all charge effects used in negative spells
5856 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5857 m_caster
->Attack(unitTarget
,true);
5860 void Spell::EffectSummonCritter(uint32 i
)
5862 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5864 Player
* player
= (Player
*)m_caster
;
5866 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5870 Pet
* old_critter
= player
->GetMiniPet();
5872 // for same pet just despawn
5873 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5875 player
->RemoveMiniPet();
5879 // despawn old pet before summon new
5881 player
->RemoveMiniPet();
5884 Pet
* critter
= new Pet(MINI_PET
);
5886 Map
*map
= m_caster
->GetMap();
5887 uint32 pet_number
= objmgr
.GeneratePetNumber();
5888 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5889 pet_entry
, pet_number
))
5891 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5897 // If dest location if present
5898 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5900 x
= m_targets
.m_destX
;
5901 y
= m_targets
.m_destY
;
5902 z
= m_targets
.m_destZ
;
5904 // Summon if dest location not present near caster
5906 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5908 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5910 if(!critter
->IsPositionValid())
5912 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5913 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5918 critter
->SetOwnerGUID(m_caster
->GetGUID());
5919 critter
->SetCreatorGUID(m_caster
->GetGUID());
5920 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5921 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5923 critter
->AIM_Initialize();
5924 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5925 critter
->SetMaxHealth(1);
5926 critter
->SetHealth(1);
5927 critter
->SetLevel(1);
5929 // set timer for unsummon
5930 int32 duration
= GetSpellDuration(m_spellInfo
);
5932 critter
->SetDuration(duration
);
5934 std::string name
= player
->GetName();
5935 name
.append(petTypeSuffix
[critter
->getPetType()]);
5936 critter
->SetName( name
);
5937 player
->SetMiniPet(critter
);
5939 map
->Add((Creature
*)critter
);
5942 void Spell::EffectKnockBack(uint32 i
)
5944 if(!unitTarget
|| !m_caster
)
5947 // Effect only works on players
5948 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5951 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5952 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5954 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5955 data
.append(unitTarget
->GetPackGUID());
5956 data
<< uint32(0); // Sequence
5957 data
<< float(vcos
); // x direction
5958 data
<< float(vsin
); // y direction
5959 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5960 data
<< float(damage
/-10); // Z Movement speed (vertical)
5962 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5965 void Spell::EffectSendTaxi(uint32 i
)
5967 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5970 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5974 std::vector
<uint32
> nodes
;
5977 nodes
[0] = entry
->from
;
5978 nodes
[1] = entry
->to
;
5981 switch(m_spellInfo
->Id
)
5983 case 31606: //Stormcrow Amulet
5986 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5987 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5988 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5991 case 34905: //Stealth Flight
5994 case 45883: //Amber Ledge to Beryl Point
5997 case 46064: //Amber Ledge to Coldarra
6000 case 53335: //Stormwind Harbor Flight - Peaceful
6005 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
6009 void Spell::EffectPlayerPull(uint32 i
)
6011 if(!unitTarget
|| !m_caster
)
6014 // Effect only works on players
6015 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6018 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6019 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6021 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
6022 data
.append(unitTarget
->GetPackGUID());
6023 data
<< uint32(0); // Sequence
6024 data
<< float(vcos
); // x direction
6025 data
<< float(vsin
); // y direction
6027 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6028 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6030 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6033 void Spell::EffectDispelMechanic(uint32 i
)
6038 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6040 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6041 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6045 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6046 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6048 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6052 next
= Auras
.begin();
6058 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6060 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6062 Player
*_player
= (Player
*)m_caster
;
6063 Pet
*pet
= _player
->GetPet();
6070 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6071 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6072 pet
->setDeathState( ALIVE
);
6073 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6074 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6076 pet
->AIM_Initialize();
6078 _player
->PetSpellInitialize();
6079 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6082 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6085 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6087 if(!m_caster
->m_TotemSlot
[slot
])
6090 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6091 if(totem
&& totem
->isTotem())
6093 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6094 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6096 mana
+= spellInfo
->manaCost
* damage
/ 100;
6097 ((Totem
*)totem
)->UnSummon();
6101 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6102 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6105 void Spell::EffectDurabilityDamage(uint32 i
)
6107 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6110 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6112 // FIXME: some spells effects have value -1/-2
6113 // Possibly its mean -1 all player equipped items and -2 all items
6116 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6120 // invalid slot value
6121 if(slot
>= INVENTORY_SLOT_BAG_END
)
6124 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6125 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6128 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6130 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6133 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6135 // FIXME: some spells effects have value -1/-2
6136 // Possibly its mean -1 all player equipped items and -2 all items
6139 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6143 // invalid slot value
6144 if(slot
>= INVENTORY_SLOT_BAG_END
)
6150 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6151 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6154 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6159 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6162 void Spell::EffectTransmitted(uint32 effIndex
)
6164 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6166 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6170 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6176 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6178 fx
= m_targets
.m_destX
;
6179 fy
= m_targets
.m_destY
;
6180 fz
= m_targets
.m_destZ
;
6182 //FIXME: this can be better check for most objects but still hack
6183 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6185 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6186 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6190 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6191 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6192 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6194 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6197 Map
*cMap
= m_caster
->GetMap();
6199 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6201 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6202 { // but this is not proper, we really need to ignore not materialized objects
6203 SendCastResult(SPELL_FAILED_NOT_HERE
);
6204 SendChannelUpdate(0);
6208 // replace by water level in this case
6209 fz
= cMap
->GetWaterLevel(fx
,fy
);
6211 // if gameobject is summoning object, it should be spawned right on caster's position
6212 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6214 m_caster
->GetPosition(fx
,fy
,fz
);
6217 GameObject
* pGameObj
= new GameObject
;
6219 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6220 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6226 int32 duration
= GetSpellDuration(m_spellInfo
);
6228 switch(goinfo
->type
)
6230 case GAMEOBJECT_TYPE_FISHINGNODE
:
6232 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6233 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6235 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6236 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6240 case 0: lastSec
= 3; break;
6241 case 1: lastSec
= 7; break;
6242 case 2: lastSec
= 13; break;
6243 case 3: lastSec
= 17; break;
6246 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6249 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6251 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6253 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6254 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6258 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6259 case GAMEOBJECT_TYPE_CHEST
:
6266 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6268 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6270 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6271 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6273 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6274 //m_caster->AddGameObject(pGameObj);
6275 //m_ObjToDel.push_back(pGameObj);
6277 cMap
->Add(pGameObj
);
6279 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6280 data
<< uint64(pGameObj
->GetGUID());
6281 m_caster
->SendMessageToSet(&data
,true);
6283 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6285 GameObject
* linkedGO
= new GameObject
;
6286 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6287 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6289 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6290 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6291 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6292 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6294 linkedGO
->GetMap()->Add(linkedGO
);
6305 void Spell::EffectProspecting(uint32
/*i*/)
6307 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6310 Player
* p_caster
= (Player
*)m_caster
;
6311 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6314 if(itemTarget
->GetCount() < 5)
6317 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6319 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6320 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6321 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6324 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6327 void Spell::EffectMilling(uint32
/*i*/)
6329 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6332 Player
* p_caster
= (Player
*)m_caster
;
6333 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6336 if(itemTarget
->GetCount() < 5)
6339 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6341 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6342 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6343 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6346 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6349 void Spell::EffectSkill(uint32
/*i*/)
6351 sLog
.outDebug("WORLD: SkillEFFECT");
6354 void Spell::EffectSummonDemon(uint32 i
)
6356 // select center of summon position
6357 float center_x
= m_targets
.m_destX
;
6358 float center_y
= m_targets
.m_destY
;
6359 float center_z
= m_targets
.m_destZ
;
6361 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6363 int32 amount
= damage
> 0 ? damage
: 1;
6365 for(int32 count
= 0; count
< amount
; ++count
)
6368 // If dest location if present
6369 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6371 // Summon 1 unit in dest location
6374 px
= m_targets
.m_destX
;
6375 py
= m_targets
.m_destY
;
6376 pz
= m_targets
.m_destZ
;
6378 // Summon in random point all other units if location present
6380 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
6382 // Summon if dest location not present near caster
6384 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
6386 int32 duration
= GetSpellDuration(m_spellInfo
);
6388 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,duration
);
6389 if (!Charmed
) // something fatal, not attempt more
6392 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6393 Charmed
->SetLevel(m_caster
->getLevel());
6395 // TODO: Add damage/mana/hp according to level
6397 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6399 // Enslave demon effect, without mana cost and cooldown
6400 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6403 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6408 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6409 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6410 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6411 This is why we use a half sec delay between the visual effect and the resurrection itself */
6412 void Spell::EffectSpiritHeal(uint32
/*i*/)
6415 if(!unitTarget || unitTarget->isAlive())
6417 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6419 if(!unitTarget->IsInWorld())
6422 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6423 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6424 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6425 ((Player*)unitTarget)->SpawnCorpseBones();
6429 // remove insignia spell effect
6430 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6432 sLog
.outDebug("Effect: SkinPlayerCorpse");
6433 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6436 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6439 void Spell::EffectStealBeneficialBuff(uint32 i
)
6441 sLog
.outDebug("Effect: StealBeneficialBuff");
6443 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6446 std::vector
<Aura
*> steal_list
;
6447 // Create dispel mask by dispel type
6448 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6449 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6450 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6452 Aura
*aur
= (*itr
).second
;
6453 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6455 // Need check for passive? this
6456 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6457 steal_list
.push_back(aur
);
6460 // Ok if exist some buffs for dispel try dispel it
6461 if (!steal_list
.empty())
6463 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6464 int32 list_size
= steal_list
.size();
6465 // Dispell N = damage buffs (or while exist buffs for dispel)
6466 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6468 // Random select buff for dispel
6469 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6470 // Not use chance for steal
6471 // TODO possible need do it
6472 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6474 // Remove buff from list for prevent doubles
6475 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6478 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6480 j
= steal_list
.erase(j
);
6487 // Really try steal and send log
6488 if (!success_list
.empty())
6490 int32 count
= success_list
.size();
6491 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6492 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6493 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6494 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6495 data
<< uint8(0); // not used
6496 data
<< uint32(count
); // count
6497 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6499 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6500 data
<< uint32(spellInfo
->Id
); // Spell Id
6501 data
<< uint8(0); // 0 - steals !=0 transfers
6502 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6504 m_caster
->SendMessageToSet(&data
, true);
6509 void Spell::EffectKillCredit(uint32 i
)
6511 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6514 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6517 void Spell::EffectQuestFail(uint32 i
)
6519 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6522 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6525 void Spell::EffectActivateRune(uint32 eff_idx
)
6527 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6530 Player
*plr
= (Player
*)m_caster
;
6532 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6535 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6537 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6539 plr
->SetRuneCooldown(j
, 0);
6544 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6546 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6547 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6550 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6552 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6553 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6556 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);