2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
26 #include "UpdateMask.h"
28 #include "ObjectMgr.h"
31 #include "SkillExtraItems.h"
33 #include "CreatureAI.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
47 #include "CreatureAI.h"
48 #include "BattleGroundMgr.h"
49 #include "BattleGround.h"
50 #include "BattleGroundEY.h"
51 #include "BattleGroundWS.h"
52 #include "VMapFactory.h"
54 #include "SocialMgr.h"
56 #include "TemporarySummon.h"
57 #include "ScriptCalls.h"
58 #include "SkillDiscovery.h"
60 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
62 &Spell::EffectNULL
, // 0
63 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
64 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
65 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
66 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
67 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
68 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
69 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
70 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
71 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
72 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
73 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
74 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
75 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
76 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
77 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
78 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
79 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
80 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
81 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
82 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
83 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
84 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
85 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
86 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
87 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
88 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
89 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
90 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
91 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
92 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
93 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
94 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
95 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
96 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
97 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
98 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
99 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
100 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
101 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
102 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
103 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
104 &Spell::EffectUnused
, // 42 SPELL_EFFECT_JUMP2
105 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
106 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
107 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
108 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
109 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
110 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
111 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
112 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
113 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
114 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
115 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
116 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
117 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
118 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
119 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
120 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
121 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
122 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
123 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
124 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
125 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
126 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
127 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
128 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
129 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
130 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
131 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
132 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
133 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
134 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
135 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
136 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
137 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
138 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
139 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
140 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
141 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
142 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
143 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
144 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
145 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
146 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
147 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
148 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
149 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
150 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
151 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
152 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
153 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
154 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
155 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
156 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
157 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
158 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
159 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
160 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
161 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
162 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
163 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
164 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
165 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
166 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
167 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
168 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
169 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
170 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
171 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
172 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
173 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
174 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
175 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
176 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
177 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
178 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
179 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
180 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
181 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
182 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
183 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
184 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
185 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
186 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
187 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
188 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
189 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
190 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
191 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
192 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
193 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
194 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
195 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
196 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
197 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
198 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
199 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
200 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
201 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
202 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
203 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
204 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
205 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
206 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
207 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
208 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
209 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
210 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
211 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
212 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
213 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
214 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
215 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
216 &Spell::EffectNULL
, //154 unused
217 &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.
218 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
219 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
220 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
221 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
224 void Spell::EffectNULL(uint32
/*i*/)
226 sLog
.outDebug("WORLD: Spell Effect DUMMY");
229 void Spell::EffectUnused(uint32
/*i*/)
231 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
234 void Spell::EffectResurrectNew(uint32 i
)
236 if(!unitTarget
|| unitTarget
->isAlive())
239 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
242 if(!unitTarget
->IsInWorld())
245 Player
* pTarget
= ((Player
*)unitTarget
);
247 if(pTarget
->isRessurectRequested()) // already have one active request
250 uint32 health
= damage
;
251 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
252 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
253 SendResurrectRequest(pTarget
);
256 void Spell::EffectInstaKill(uint32
/*i*/)
258 if( !unitTarget
|| !unitTarget
->isAlive() )
262 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
264 uint32 entry
= unitTarget
->GetEntry();
268 case 416: spellID
=18789; break; //imp
269 case 417: spellID
=18792; break; //fellhunter
270 case 1860: spellID
=18790; break; //void
271 case 1863: spellID
=18791; break; //succubus
272 case 17252: spellID
=35701; break; //fellguard
274 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
278 m_caster
->CastSpell(m_caster
,spellID
,true);
281 if(m_caster
==unitTarget
) // prevent interrupt message
284 uint32 health
= unitTarget
->GetHealth();
285 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
288 void Spell::EffectEnvirinmentalDMG(uint32 i
)
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
298 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
300 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
301 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
302 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
305 void Spell::EffectSchoolDMG(uint32 effect_idx
)
307 if( unitTarget
&& unitTarget
->isAlive())
309 switch(m_spellInfo
->SpellFamilyName
)
311 case SPELLFAMILY_GENERIC
:
314 if(m_spellInfo
->SpellIconID
== 2269 )
316 damage
+= rand()%2 ? damage
: 0;
319 switch(m_spellInfo
->Id
) // better way to check unknown
321 // Meteor like spells (divided damage to targets)
322 case 24340: case 26558: case 28884: // Meteor
323 case 36837: case 38903: case 41276: // Meteor
324 case 26789: // Shard of the Fallen Star
325 case 31436: // Malevolent Cleave
326 case 35181: // Dive Bomb
327 case 40810: case 43267: case 43268: // Saber Lash
328 case 42384: // Brutal Swipe
329 case 45150: // Meteor Slash
332 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
333 if(ihit
->effectMask
& (1<<effect_idx
))
336 damage
/= count
; // divide to all targets
339 // percent from health with min
340 case 25599: // Thundercrash
342 damage
= unitTarget
->GetHealth() / 2;
347 // Intercept (warrior spell trigger)
351 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
358 case SPELLFAMILY_MAGE
:
361 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
363 m_caster
->CastSpell(m_caster
,36032,true);
367 case SPELLFAMILY_WARRIOR
:
370 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
372 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
375 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
376 damage
+= int32(m_caster
->GetShieldBlockValue());
378 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
380 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
381 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
383 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
384 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
385 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
386 // Heroic Throw ${$m1+$AP*.50}
387 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
388 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
389 // Shockwave ${$m3/100*$AP}
390 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
392 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
394 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
399 case SPELLFAMILY_WARLOCK
:
401 // Incinerate Rank 1 & 2
402 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
404 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
405 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
406 damage
+= int32(damage
*0.25f
);
410 case SPELLFAMILY_PRIEST
:
412 // Shadow Word: Death - deals damage equal to damage done to caster
413 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
414 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
417 case SPELLFAMILY_DRUID
:
420 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
422 // converts each extra point of energy into ($f1+$AP/410) additional damage
423 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
424 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
425 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
426 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
427 m_caster
->SetPower(POWER_ENERGY
,0);
430 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
432 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
435 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
437 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
439 //Mangle Bonus for the initial damage of Lacerate and Rake
440 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
441 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
443 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
444 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
445 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
447 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
453 case SPELLFAMILY_ROGUE
:
456 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
458 // consume from stack dozes not more that have combo-points
459 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
462 // Lookup for Deadly poison (only attacker applied)
463 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
464 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
465 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
466 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
467 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
472 // count consumed deadly poison doses at target
475 uint32 spellId
= poison
->GetId();
476 uint32 doses
= poison
->GetStackAmount();
479 for (int i
=0; i
< doses
; i
++)
480 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
482 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
484 // Eviscerate and Envenom Bonus Damage (item set effect)
485 if(m_caster
->GetDummyAura(37169))
486 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
490 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
492 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
494 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
495 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
497 // Eviscerate and Envenom Bonus Damage (item set effect)
498 if(m_caster
->GetDummyAura(37169))
503 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
505 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
508 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
510 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
513 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
515 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
519 case SPELLFAMILY_HUNTER
:
522 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
524 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
527 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
529 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
532 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
534 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
537 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
539 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
540 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
542 // Explosive Trap Effect
543 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
545 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
549 case SPELLFAMILY_PALADIN
:
551 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
552 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
554 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
555 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
556 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
557 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
558 // Get stack of Holy Vengeance on the target added by caster
560 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
561 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
562 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
564 stacks
= (*itr
)->GetStackAmount();
567 // + 10% for each application of Holy Vengeance on the target
569 damage
+= damage
* stacks
* 10 /100;
571 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
572 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
574 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
575 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
576 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
577 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
579 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
580 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
582 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
583 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
584 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
585 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
587 // Hammer of the Righteous
588 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
590 // Add main hand dps * effect[2] amount
591 float averange
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
592 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
593 damage
+= count
* int32(averange
* 1000) / m_caster
->GetAttackTime(BASE_ATTACK
);
604 void Spell::EffectDummy(uint32 i
)
606 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
609 // selection by spell family
610 switch(m_spellInfo
->SpellFamilyName
)
612 case SPELLFAMILY_GENERIC
:
614 switch(m_spellInfo
->Id
)
616 case 8063: // Deviate Fish
618 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
624 case 1: spell_id
= 8064; break; // Sleepy
625 case 2: spell_id
= 8065; break; // Invigorate
626 case 3: spell_id
= 8066; break; // Shrink
627 case 4: spell_id
= 8067; break; // Party Time!
628 case 5: spell_id
= 8068; break; // Healthy Spirit
630 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
633 case 8213: // Savory Deviate Delight
635 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
642 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
644 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
646 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
649 case 8593: // Symbol of life (restore creature to life)
650 case 31225: // Shimmering Vessel (restore creature to life)
652 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
654 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
657 case 12162: // Deep wounds
658 case 12850: // (now good common check for this spells)
665 // DW should benefit of attack power, damage percent mods etc.
666 // TODO: check if using offhand damage is correct and if it should be divided by 2
667 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
668 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
670 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
672 switch (m_spellInfo
->Id
)
674 case 12850: damage
*= 0.2f
; break;
675 case 12162: damage
*= 0.4f
; break;
676 case 12868: damage
*= 0.6f
; break;
678 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
682 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
683 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
686 case 13120: // net-o-matic
693 uint32 roll
= urand(0, 99);
695 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
697 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
702 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
705 case 13567: // Dummy Trigger
707 // can be used for different aura triggering, so select by aura
708 if(!m_triggeredByAuraSpell
|| !unitTarget
)
711 switch(m_triggeredByAuraSpell
->Id
)
713 case 26467: // Persistent Shield
714 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
717 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
722 case 15998: // Capture Worg Pup
723 case 29435: // Capture Female Kaliri Hatchling
725 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
728 Creature
* creatureTarget
= (Creature
*)unitTarget
;
729 creatureTarget
->setDeathState(JUST_DIED
);
730 creatureTarget
->RemoveCorpse();
731 creatureTarget
->SetHealth(0); // just for nice GM-mode view
734 case 16589: // Noggenfogger Elixir
736 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
742 case 1: spell_id
= 16595; break;
743 case 2: spell_id
= 16593; break;
744 default:spell_id
= 16591; break;
747 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
750 case 17251: // Spirit Healer Res
752 if(!unitTarget
|| !m_originalCaster
)
755 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
757 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
758 data
<< unitTarget
->GetGUID();
759 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
763 case 17271: // Test Fetid Skull
765 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
768 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
770 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
773 case 20577: // Cannibalize
775 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
777 case 23019: // Crystal Prison Dummy DND
779 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
782 Creature
* creatureTarget
= (Creature
*)unitTarget
;
783 if(creatureTarget
->isPet())
786 GameObject
* pGameObj
= new GameObject
;
788 Map
*map
= creatureTarget
->GetMap();
790 // create before death for get proper coordinates
791 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
792 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
793 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
799 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
800 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
801 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
802 pGameObj
->SetSpellId(m_spellInfo
->Id
);
804 creatureTarget
->setDeathState(JUST_DIED
);
805 creatureTarget
->RemoveCorpse();
806 creatureTarget
->SetHealth(0); // just for nice GM-mode view
808 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
811 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
812 data
<< uint64(pGameObj
->GetGUID());
813 m_caster
->SendMessageToSet(&data
,true);
817 case 23074: // Arcanite Dragonling
818 if (!m_CastItem
) return;
819 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
821 case 23075: // Mithril Mechanical Dragonling
822 if (!m_CastItem
) return;
823 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
825 case 23076: // Mechanical Dragonling
826 if (!m_CastItem
) return;
827 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
829 case 23133: // Gnomish Battle Chicken
830 if (!m_CastItem
) return;
831 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
833 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
835 int32 r
= irand(0, 119);
836 if ( r
< 20 ) // 1/6 polymorph
837 m_caster
->CastSpell(m_caster
,23444,true);
838 else if ( r
< 100 ) // 4/6 evil twin
839 m_caster
->CastSpell(m_caster
,23445,true);
840 else // 1/6 miss the target
841 m_caster
->CastSpell(m_caster
,36902,true);
844 case 23453: // Ultrasafe Transporter: Gadgetzan
845 if ( roll_chance_i(50) ) // success
846 m_caster
->CastSpell(m_caster
,23441,true);
848 m_caster
->CastSpell(m_caster
,23446,true);
850 case 23645: // Hourglass Sand
851 m_caster
->RemoveAurasDueToSpell(23170);
853 case 23725: // Gift of Life (warrior bwl trinket)
854 m_caster
->CastSpell(m_caster
,23782,true);
855 m_caster
->CastSpell(m_caster
,23783,true);
857 case 25860: // Reindeer Transformation
859 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
862 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
863 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
865 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
867 //5 different spells used depending on mounted speed and if mount can fly or not
868 if (flyspeed
>= 4.1f
)
869 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
870 else if (flyspeed
>= 3.8f
)
871 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
872 else if (flyspeed
>= 1.6f
)
873 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
874 else if (speed
>= 2.0f
)
875 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
877 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
881 //case 26074: // Holiday Cheer
882 // return; -- implemented at client side
883 case 28006: // Arcane Cloaking
885 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
886 m_caster
->CastSpell(unitTarget
,29294,true);
889 case 28730: // Arcane Torrent (Mana)
891 Aura
* dummy
= m_caster
->GetDummyAura(28734);
894 int32 bp
= damage
* dummy
->GetStackAmount();
895 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
896 m_caster
->RemoveAurasDueToSpell(28734);
900 case 29200: // Purify Helboar Meat
902 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
905 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
907 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
910 case 29858: // Soulshatter
911 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
912 m_caster
->CastSpell(unitTarget
,32835,true);
914 case 30458: // Nigh Invulnerability
915 if (!m_CastItem
) return;
916 if(roll_chance_i(86)) // success
917 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
918 else // backfire in 14% casts
919 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
921 case 30507: // Poultryizer
922 if (!m_CastItem
) return;
923 if(roll_chance_i(80)) // success
924 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
926 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
928 case 33060: // Make a Wish
930 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
937 case 1: spell_id
= 33053; break;
938 case 2: spell_id
= 33057; break;
939 case 3: spell_id
= 33059; break;
940 case 4: spell_id
= 33062; break;
941 case 5: spell_id
= 33064; break;
944 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
950 switch(m_caster
->GetAreaId())
952 case 3900: spell_id
= 35743; break;
953 case 3742: spell_id
= 35744; break;
957 m_caster
->CastSpell(m_caster
,spell_id
,true);
960 case 37674: // Chaos Blast
965 int32 basepoints0
= 100;
966 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
969 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
971 // selecting one from Bloodstained Fortune item
975 case 1: newitemid
= 32688; break;
976 case 2: newitemid
= 32689; break;
977 case 3: newitemid
= 32690; break;
978 case 4: newitemid
= 32691; break;
979 case 5: newitemid
= 32692; break;
980 case 6: newitemid
= 32693; break;
981 case 7: newitemid
= 32700; break;
982 case 8: newitemid
= 32701; break;
983 case 9: newitemid
= 32702; break;
984 case 10: newitemid
= 32703; break;
985 case 11: newitemid
= 32704; break;
986 case 12: newitemid
= 32705; break;
987 case 13: newitemid
= 32706; break;
988 case 14: newitemid
= 32707; break;
989 case 15: newitemid
= 32708; break;
990 case 16: newitemid
= 32709; break;
991 case 17: newitemid
= 32710; break;
992 case 18: newitemid
= 32711; break;
993 case 19: newitemid
= 32712; break;
994 case 20: newitemid
= 32713; break;
999 DoCreateItem(i
,newitemid
);
1002 // Demon Broiled Surprise
1003 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1006 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1009 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1013 case 44875: // Complete Raptor Capture
1015 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1018 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1020 creatureTarget
->setDeathState(JUST_DIED
);
1021 creatureTarget
->RemoveCorpse();
1022 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1024 //cast spell Raptor Capture Credit
1025 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1028 case 34665: //Administer Antidote
1030 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1036 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1040 uint32 health
= tempSummon
->GetHealth();
1042 float x
= tempSummon
->GetPositionX();
1043 float y
= tempSummon
->GetPositionY();
1044 float z
= tempSummon
->GetPositionZ();
1045 float o
= tempSummon
->GetOrientation();
1046 tempSummon
->UnSummon();
1048 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1052 pCreature
->SetHealth(health
);
1053 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1055 if (pCreature
->AI())
1056 pCreature
->AI()->AttackStart(m_caster
);
1060 case 44997: // Converting Sentry
1062 //Converted Sentry Credit
1063 m_caster
->CastSpell(m_caster
, 45009, true);
1066 case 45030: // Impale Emissary
1068 // Emissary of Hate Credit
1069 m_caster
->CastSpell(m_caster
, 45088, true);
1072 case 50243: // Teach Language
1074 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1077 // spell has a 1/3 chance to trigger one of the below
1078 if(roll_chance_i(66))
1080 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1082 // 1000001 - gnomish binary
1083 m_caster
->CastSpell(m_caster
, 50242, true);
1087 // 01001000 - goblin binary
1088 m_caster
->CastSpell(m_caster
, 50246, true);
1093 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1095 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1098 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1099 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1101 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1107 m_caster
->CastSpell(m_caster
,54586,true);
1112 //All IconID Check in there
1113 switch(m_spellInfo
->SpellIconID
)
1115 // Berserking (troll racial traits)
1118 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1119 int32 melee_mod
= 10;
1120 if (healthPerc
<= 40)
1122 if (healthPerc
< 100 && healthPerc
> 40)
1123 melee_mod
= 10+(100-healthPerc
)/3;
1125 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1126 int32 hasteModBasePoints1
= (5-melee_mod
);
1127 int32 hasteModBasePoints2
= 5;
1129 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1130 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1131 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1137 case SPELLFAMILY_MAGE
:
1138 switch(m_spellInfo
->Id
)
1140 case 11958: // Cold Snap
1142 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1145 // immediately finishes the cooldown on Frost spells
1146 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1147 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1149 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1152 uint32 classspell
= itr
->first
;
1153 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1155 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1156 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1157 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1159 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1161 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1162 data
<< uint32(classspell
);
1163 data
<< uint64(m_caster
->GetGUID());
1164 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1171 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1173 //Polymorph Cast Visual Rank 1
1174 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1175 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1181 case SPELLFAMILY_WARRIOR
:
1183 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1185 int32 chargeBasePoints0
= damage
;
1186 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1190 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1195 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1196 // Glyph of Execution bonus
1197 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1198 rage
+=aura
->GetModifier()->m_amount
;
1200 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1201 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1202 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1203 m_caster
->SetPower(POWER_RAGE
,0);
1207 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1211 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1215 switch(m_spellInfo
->Id
)
1222 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1228 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1229 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1235 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1240 case SPELLFAMILY_WARLOCK
:
1242 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1244 // In 303 exist spirit depend
1245 uint32 spirit
= m_caster
->GetStat(STAT_SPIRIT
);
1246 switch (m_spellInfo
->Id
)
1248 case 1454: damage
+=spirit
; break;
1249 case 1455: damage
+=spirit
*15/10; break;
1250 case 1456: damage
+=spirit
*2; break;
1251 case 11687: damage
+=spirit
*25/10; break;
1255 case 57946: damage
+=spirit
*3; break;
1257 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1260 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1261 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1262 if(int32(unitTarget
->GetHealth()) > damage
)
1264 // Shouldn't Appear in Combat Log
1265 unitTarget
->ModifyHealth(-damage
);
1267 int32 mana
= damage
;
1268 // Improved Life Tap mod
1269 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1270 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1272 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1273 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1275 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1278 int32 manaFeedVal
= 0;
1279 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1280 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1282 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1283 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1287 manaFeedVal
= manaFeedVal
* mana
/ 100;
1288 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1292 SendCastResult(SPELL_FAILED_FIZZLE
);
1296 case SPELLFAMILY_PRIEST
:
1298 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1305 switch(m_spellInfo
->Id
)
1307 case 47540: hurt
= 47758; heal
= 47757; break;
1308 case 53005: hurt
= 53001; heal
= 52986; break;
1309 case 53006: hurt
= 53002; heal
= 52987; break;
1310 case 53007: hurt
= 53003; heal
= 52988; break;
1312 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1315 if (m_caster
->IsFriendlyTo(unitTarget
))
1316 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1318 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1321 switch(m_spellInfo
->Id
)
1323 case 28598: // Touch of Weakness triggered spell
1325 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1329 switch(m_triggeredByAuraSpell
->Id
)
1331 case 2652: spellid
= 2943; break; // Rank 1
1332 case 19261: spellid
= 19249; break; // Rank 2
1333 case 19262: spellid
= 19251; break; // Rank 3
1334 case 19264: spellid
= 19252; break; // Rank 4
1335 case 19265: spellid
= 19253; break; // Rank 5
1336 case 19266: spellid
= 19254; break; // Rank 6
1337 case 25461: spellid
= 25460; break; // Rank 7
1339 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1342 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1347 case SPELLFAMILY_DRUID
:
1349 case SPELLFAMILY_ROGUE
:
1350 switch(m_spellInfo
->Id
)
1354 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1357 Player
*pCaster
= ((Player
*)m_caster
);
1359 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1363 // all poison enchantments is temporary
1364 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1368 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1372 for (int s
=0;s
<3;s
++)
1374 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1377 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1378 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1381 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1384 m_caster
->CastSpell(unitTarget
, 5940, true);
1387 case 14185: // Preparation Rogue
1389 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1392 //immediately finishes the cooldown on certain Rogue abilities
1393 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1394 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1396 uint32 classspell
= itr
->first
;
1397 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1399 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1401 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1403 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1404 data
<< uint32(classspell
);
1405 data
<< uint64(m_caster
->GetGUID());
1406 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1411 case 31231: // Cheat Death
1413 m_caster
->CastSpell(m_caster
,45182,true);
1418 case SPELLFAMILY_HUNTER
:
1420 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1422 if( !unitTarget
|| !unitTarget
->isAlive())
1427 // check dazed affect
1428 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1429 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1431 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1443 switch(m_spellInfo
->Id
)
1445 case 23989: //Readiness talent
1447 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1450 //immediately finishes the cooldown for hunter abilities
1451 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1452 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1454 uint32 classspell
= itr
->first
;
1455 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1457 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1459 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1461 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1462 data
<< uint32(classspell
);
1463 data
<< uint64(m_caster
->GetGUID());
1464 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1469 case 37506: // Scatter Shot
1471 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1474 // break Auto Shot and autohit
1475 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1476 m_caster
->AttackStop();
1477 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1482 case SPELLFAMILY_PALADIN
:
1483 switch(m_spellInfo
->SpellIconID
)
1485 case 156: // Holy Shock
1493 switch(m_spellInfo
->Id
)
1495 case 20473: hurt
= 25912; heal
= 25914; break;
1496 case 20929: hurt
= 25911; heal
= 25913; break;
1497 case 20930: hurt
= 25902; heal
= 25903; break;
1498 case 27174: hurt
= 27176; heal
= 27175; break;
1499 case 33072: hurt
= 33073; heal
= 33074; break;
1500 case 48824: hurt
= 48822; heal
= 48820; break;
1501 case 48825: hurt
= 48823; heal
= 48821; break;
1503 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1507 if(m_caster
->IsFriendlyTo(unitTarget
))
1508 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1510 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1514 case 561: // Judgement of command
1519 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1520 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1524 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1526 // decreased damage (/2) for non-stunned target.
1527 SpellModifier
*mod
= new SpellModifier
;
1528 mod
->op
= SPELLMOD_DAMAGE
;
1530 mod
->type
= SPELLMOD_PCT
;
1531 mod
->spellId
= m_spellInfo
->Id
;
1532 mod
->mask
= 0x0000020000000000LL
;
1535 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1536 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1538 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1541 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1547 switch(m_spellInfo
->Id
)
1549 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1554 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1557 case 31789: // Righteous Defense (step 1)
1559 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1561 // non-standard cast requirement check
1562 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1564 // clear cooldown at fail
1565 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1567 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1569 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1570 data
<< uint32(m_spellInfo
->Id
);
1571 data
<< uint64(m_caster
->GetGUID());
1572 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1575 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1579 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1580 // Clear targets for eff 1
1581 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1582 ihit
->effectMask
&= ~(1<<1);
1584 // not empty (checked)
1585 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1587 // chance to be selected from list
1588 float chance
= 100.0f
/attackers
.size();
1590 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1592 if(!roll_chance_f(chance
))
1595 AddUnitTarget((*aItr
), 1);
1598 // now let next effect cast spell at each target.
1601 case 37877: // Blessing of Faith
1606 uint32 spell_id
= 0;
1607 switch(unitTarget
->getClass())
1609 case CLASS_DRUID
: spell_id
= 37878; break;
1610 case CLASS_PALADIN
: spell_id
= 37879; break;
1611 case CLASS_PRIEST
: spell_id
= 37880; break;
1612 case CLASS_SHAMAN
: spell_id
= 37881; break;
1613 default: return; // ignore for not healing classes
1616 m_caster
->CastSpell(m_caster
,spell_id
,true);
1621 case SPELLFAMILY_SHAMAN
:
1622 //Shaman Rockbiter Weapon
1623 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1625 // TODO: use expect spell for enchant (if exist talent)
1626 // In 3.0.3 no mods present for rockbiter
1627 uint32 spell_id
= 0;
1628 switch(m_spellInfo
->Id
)
1630 case 8017: spell_id
= 36494; break; // Rank 1
1631 case 8018: spell_id
= 36750; break; // Rank 2
1632 case 8019: spell_id
= 36755; break; // Rank 3
1633 case 10399: spell_id
= 36759; break; // Rank 4
1635 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1639 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1643 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1647 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1650 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1652 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1654 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1656 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1658 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1659 // at calculation applied affect from Elemental Weapons talent
1660 // real enchantment damage-1
1661 spell
->m_currentBasePoints
[1] = damage
-1;
1663 SpellCastTargets targets
;
1664 targets
.setItemTarget( item
);
1665 spell
->prepare(&targets
);
1671 // Healing Stream Totem
1672 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1674 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1677 // Mana Spring Totem
1678 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1680 if(unitTarget
->getPowerType()!=POWER_MANA
)
1682 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1685 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1687 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1689 // Glyph of Mana Tide
1690 Unit
*owner
= m_caster
->GetOwner();
1692 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1693 damage
+=dummy
->GetModifier()->m_amount
;
1694 // Regenerate 6% of Total Mana Every 3 secs
1695 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1696 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1700 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1702 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1704 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1707 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1708 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1709 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1711 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1712 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1713 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1715 m_damage
+= m_damage
* damage
/ 100;
1726 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1728 m_caster
->AddPetAura(petSpell
);
1733 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1735 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1738 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1742 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1747 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1750 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1752 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1753 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1757 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1762 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1764 SpellCastTargets targets
;
1765 targets
.setUnitTarget( unitTarget
);
1766 spell
->prepare(&targets
);
1768 m_caster
->SetCurrentCastedSpell(spell
);
1769 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1773 void Spell::EffectForceCast(uint32 i
)
1778 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1781 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1785 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1789 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1792 void Spell::EffectTriggerSpell(uint32 i
)
1794 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1797 switch(triggered_spell_id
)
1802 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1803 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1804 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1806 // if this spell is given to NPC it must handle rest by it's own AI
1807 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1810 // get highest rank of the Stealth spell
1812 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1813 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1815 // only highest rank is shown in spell book, so simply check if shown in spell book
1816 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1819 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1823 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1825 spellId
= spellInfo
->Id
;
1830 // no Stealth spell found
1834 // reset cooldown on it if needed
1835 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1836 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1838 m_caster
->CastSpell(m_caster
, spellId
, true);
1842 case 23770: // Sayge's Dark Fortune of *
1843 // not exist, common cooldown can be implemented in scripts if need.
1845 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1848 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1852 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1853 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1856 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1859 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1863 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1864 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1867 // Righteous Defense
1870 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1876 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1877 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1879 // remove all harmful spells on you...
1880 if( // ignore positive and passive auras
1881 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1882 // ignore physical auras
1883 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1885 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1886 iter
= Auras
.begin();
1891 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1894 if (Unit
*pet
= m_caster
->GetPet())
1895 pet
->CastSpell(pet
, 28305, true);
1901 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1905 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1909 // some triggered spells require specific equipment
1910 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1912 // main hand weapon required
1913 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1915 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1917 // skip spell if no weapon in slot or broken
1918 if(!item
|| item
->IsBroken() )
1921 // skip spell if weapon not fit to triggered spell
1922 if(!item
->IsFitToSpellRequirements(spellInfo
))
1926 // offhand hand weapon required
1927 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1929 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1931 // skip spell if no weapon in slot or broken
1932 if(!item
|| item
->IsBroken() )
1935 // skip spell if weapon not fit to triggered spell
1936 if(!item
->IsFitToSpellRequirements(spellInfo
))
1941 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1942 bool instant
= false;
1943 for(uint32 j
= i
+1; j
< 3; ++j
)
1945 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1955 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1958 m_TriggerSpells
.push_back(spellInfo
);
1961 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
1963 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
1966 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1970 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1971 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
1976 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
1978 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
1981 void Spell::EffectTeleportUnits(uint32 i
)
1983 if(!unitTarget
|| unitTarget
->isInFlight())
1986 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
1988 case TARGET_INNKEEPER_COORDINATES
:
1990 // Only players can teleport to innkeeper
1991 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1994 ((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);
1997 case TARGET_TABLE_X_Y_Z_COORDINATES
:
1999 // TODO: Only players can teleport?
2000 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2002 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2005 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
2008 ((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);
2011 case TARGET_BEHIND_VICTIM
:
2013 // Get selected target for player (or victim for units)
2014 Unit
*pTarget
= NULL
;
2015 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2016 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2018 pTarget
= m_caster
->getVictim();
2019 // No target present - return
2022 // Init dest coordinates
2023 uint32 mapid
= m_caster
->GetMapId();
2024 float x
= m_targets
.m_destX
;
2025 float y
= m_targets
.m_destY
;
2026 float z
= m_targets
.m_destZ
;
2027 float orientation
= pTarget
->GetOrientation();
2029 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2030 ((Player
*)unitTarget
)->TeleportTo(mapid
, x
, y
, z
, orientation
, TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
2033 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2035 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2036 unitTarget
->SendMessageToSet(&data
, false);
2042 // If not exist data for dest location - return
2043 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2045 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2048 // Init dest coordinates
2049 uint32 mapid
= m_caster
->GetMapId();
2050 float x
= m_targets
.m_destX
;
2051 float y
= m_targets
.m_destY
;
2052 float z
= m_targets
.m_destZ
;
2053 float orientation
= unitTarget
->GetOrientation();
2055 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2056 ((Player
*)unitTarget
)->TeleportTo(mapid
, x
, y
, z
, orientation
, TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
2059 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2061 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2062 unitTarget
->SendMessageToSet(&data
, false);
2068 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2069 switch ( m_spellInfo
->Id
)
2071 // Dimensional Ripper - Everlook
2074 int32 r
= irand(0, 119);
2075 if ( r
>= 70 ) // 7/12 success
2077 if ( r
< 100 ) // 4/12 evil twin
2078 m_caster
->CastSpell(m_caster
,23445,true);
2080 m_caster
->CastSpell(m_caster
,23449,true);
2084 // Ultrasafe Transporter: Toshley's Station
2087 if ( roll_chance_i(50) ) // 50% success
2089 int32 rand_eff
= urand(1,7);
2093 // soul split - evil
2094 m_caster
->CastSpell(m_caster
,36900,true);
2097 // soul split - good
2098 m_caster
->CastSpell(m_caster
,36901,true);
2101 // Increase the size
2102 m_caster
->CastSpell(m_caster
,36895,true);
2105 // Decrease the size
2106 m_caster
->CastSpell(m_caster
,36893,true);
2111 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2112 m_caster
->CastSpell(m_caster
,36897,true);
2114 m_caster
->CastSpell(m_caster
,36899,true);
2119 m_caster
->CastSpell(m_caster
,36940,true);
2123 m_caster
->CastSpell(m_caster
,23445,true);
2129 // Dimensional Ripper - Area 52
2132 if ( roll_chance_i(50) ) // 50% success
2134 int32 rand_eff
= urand(1,4);
2138 // soul split - evil
2139 m_caster
->CastSpell(m_caster
,36900,true);
2142 // soul split - good
2143 m_caster
->CastSpell(m_caster
,36901,true);
2146 // Increase the size
2147 m_caster
->CastSpell(m_caster
,36895,true);
2152 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2153 m_caster
->CastSpell(m_caster
,36897,true);
2155 m_caster
->CastSpell(m_caster
,36899,true);
2165 void Spell::EffectApplyAura(uint32 i
)
2170 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2171 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2172 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2175 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2179 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2181 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2183 // Now Reduce spell duration using data received at spell hit
2184 int32 duration
= Aur
->GetAuraMaxDuration();
2185 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2186 Aur
->setDiminishGroup(m_diminishGroup
);
2188 // if Aura removed and deleted, do not continue.
2189 if(duration
== 0 && !(Aur
->IsPermanent()))
2195 if(duration
!= Aur
->GetAuraMaxDuration())
2197 Aur
->SetAuraMaxDuration(duration
);
2198 Aur
->SetAuraDuration(duration
);
2201 bool added
= unitTarget
->AddAura(Aur
);
2203 // Aura not added and deleted in AddAura call;
2207 // found crash at character loading, broken pointer to Aur...
2208 // Aur was deleted in AddAura()...
2212 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2213 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2214 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2217 void Spell::EffectUnlearnSpecialization( uint32 i
)
2219 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2222 Player
*_player
= (Player
*)unitTarget
;
2223 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2225 _player
->removeSpell(spellToUnlearn
);
2227 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2230 void Spell::EffectPowerDrain(uint32 i
)
2232 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2235 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2239 if(!unitTarget
->isAlive())
2241 if(unitTarget
->getPowerType() != drain_power
)
2246 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2248 //add spell damage bonus
2249 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2251 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2252 uint32 power
= damage
;
2253 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2254 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2257 if(curPower
< power
)
2258 new_damage
= curPower
;
2262 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2264 // Don`t restore from self drain
2265 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2267 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2268 if(manaMultiplier
==0)
2271 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2272 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2274 int32 gain
= int32(new_damage
*manaMultiplier
);
2276 m_caster
->ModifyPower(POWER_MANA
,gain
);
2278 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2282 void Spell::EffectSendEvent(uint32 EffectIndex
)
2284 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2286 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2287 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2289 switch(m_spellInfo
->Id
)
2291 case 23333: // Pickup Horde Flag
2292 /*do not uncomment .
2293 if(bg->GetTypeID()==BATTLEGROUND_WS)
2294 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2295 sLog.outDebug("Send Event Horde Flag Picked Up");
2298 case 23334: // Drop Horde Flag
2299 if(bg->GetTypeID()==BATTLEGROUND_WS)
2300 bg->EventPlayerDroppedFlag((Player*)m_caster);
2301 sLog.outDebug("Drop Horde Flag");
2304 case 23335: // Pickup Alliance Flag
2305 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2306 if(bg->GetTypeID()==BATTLEGROUND_WS)
2307 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2308 sLog.outDebug("Send Event Alliance Flag Picked Up");
2311 case 23336: // Drop Alliance Flag
2312 if(bg->GetTypeID()==BATTLEGROUND_WS)
2313 bg->EventPlayerDroppedFlag((Player*)m_caster);
2314 sLog.outDebug("Drop Alliance Flag");
2316 case 23385: // Alliance Flag Returns
2317 if(bg->GetTypeID()==BATTLEGROUND_WS)
2318 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2319 sLog.outDebug("Alliance Flag Returned");
2321 case 23386: // Horde Flag Returns
2322 if(bg->GetTypeID()==BATTLEGROUND_WS)
2323 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2324 sLog.outDebug("Horde Flag Returned");
2328 if(bg->GetTypeID()==BATTLEGROUND_EY)
2329 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2333 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2338 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2339 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2342 void Spell::EffectPowerBurn(uint32 i
)
2344 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2347 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2351 if(!unitTarget
->isAlive())
2353 if(unitTarget
->getPowerType()!=powertype
)
2358 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2360 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2361 uint32 power
= damage
;
2362 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2363 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2365 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2367 unitTarget
->ModifyPower(powertype
,-new_damage
);
2368 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2370 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2371 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2373 new_damage
= int32(new_damage
*multiplier
);
2374 m_damage
+=new_damage
;
2377 void Spell::EffectHeal( uint32
/*i*/ )
2379 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2381 // Try to get original caster
2382 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2384 // Skip if m_originalCaster not available
2388 int32 addhealth
= damage
;
2390 // Vessel of the Naaru (Vial of the Sunwell trinket)
2391 if (m_spellInfo
->Id
== 45064)
2393 // Amount of heal - depends from stacked Holy Energy
2394 int damageAmount
= 0;
2395 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2396 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2397 if((*i
)->GetId() == 45062)
2398 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2400 m_caster
->RemoveAurasDueToSpell(45062);
2402 addhealth
+= damageAmount
;
2404 // Swiftmend - consumes Regrowth or Rejuvenation
2405 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2407 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2408 // find most short by duration
2409 Aura
*targetAura
= NULL
;
2410 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2412 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2413 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2415 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2422 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2428 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2433 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2434 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2435 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2437 addhealth
+= tickheal
* tickcount
;
2440 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2442 m_healing
+=addhealth
;
2446 void Spell::EffectHealPct( uint32
/*i*/ )
2448 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2450 // Try to get original caster
2451 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2453 // Skip if m_originalCaster not available
2457 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2458 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2460 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2461 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2463 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2464 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2465 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2469 void Spell::EffectHealMechanical( uint32
/*i*/ )
2471 // Mechanic creature type should be correctly checked by targetCreatureType field
2472 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2474 // Try to get original caster
2475 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2477 // Skip if m_originalCaster not available
2481 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2482 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2483 unitTarget
->ModifyHealth( int32(damage
) );
2487 void Spell::EffectHealthLeech(uint32 i
)
2491 if(!unitTarget
->isAlive())
2497 sLog
.outDebug("HealthLeech :%i", damage
);
2499 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2501 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2502 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2504 int32 new_damage
= int32(damage
*multiplier
);
2505 uint32 curHealth
= unitTarget
->GetHealth();
2506 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2507 if(curHealth
< new_damage
)
2508 new_damage
= curHealth
;
2510 if(m_caster
->isAlive())
2512 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2514 m_caster
->ModifyHealth(new_damage
);
2516 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2517 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2519 // m_healthLeech+=tmpvalue;
2520 // m_damage+=new_damage;
2523 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2525 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2528 Player
* player
= (Player
*)unitTarget
;
2530 uint32 newitemid
= itemtype
;
2531 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2534 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2540 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2541 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2543 int32 basePoints
= m_currentBasePoints
[i
];
2544 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2546 num_to_add
= basePoints
+ irand(1, randomPoints
);
2548 num_to_add
= basePoints
+ 1;
2550 else if (pProto
->MaxCount
== 1)
2552 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2554 int32 basePoints
= m_currentBasePoints
[i
];
2555 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2556 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2563 if (num_to_add
> pProto
->GetMaxStackSize())
2564 num_to_add
= pProto
->GetMaxStackSize();
2566 // init items_count to 1, since 1 item will be created regardless of specialization
2568 // the chance to create additional items
2569 float additionalCreateChance
=0.0f
;
2570 // the maximum number of created additional items
2571 uint8 additionalMaxNum
=0;
2572 // get the chance and maximum number for creating extra items
2573 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2575 // roll with this chance till we roll not to create or we create the max num
2576 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2580 // really will be created more items
2581 num_to_add
*= items_count
;
2583 // can the player store the new item?
2584 ItemPosCountVec dest
;
2585 uint32 no_space
= 0;
2586 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2587 if( msg
!= EQUIP_ERR_OK
)
2589 // convert to possible store amount
2590 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2591 num_to_add
-= no_space
;
2594 // if not created by another reason from full inventory or unique items amount limitation
2595 player
->SendEquipError( msg
, NULL
, NULL
);
2602 // create the new item and store it
2603 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2605 // was it successful? return error if not
2608 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2612 // set the "Crafted by ..." property of the item
2613 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2614 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2616 // send info to the client
2618 player
->SendNewItem(pItem
, num_to_add
, true, true);
2620 // we succeeded in creating at least one item, so a levelup is possible
2621 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2624 // for battleground marks send by mail if not add all expected
2627 BattleGroundTypeId bgType
;
2628 switch(m_spellInfo
->Id
)
2630 case SPELL_AV_MARK_WINNER
:
2631 case SPELL_AV_MARK_LOSER
:
2632 bgType
= BATTLEGROUND_AV
;
2634 case SPELL_WS_MARK_WINNER
:
2635 case SPELL_WS_MARK_LOSER
:
2636 bgType
= BATTLEGROUND_WS
;
2638 case SPELL_AB_MARK_WINNER
:
2639 case SPELL_AB_MARK_LOSER
:
2640 bgType
= BATTLEGROUND_AB
;
2646 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2647 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2651 void Spell::EffectCreateItem(uint32 i
)
2653 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2656 void Spell::EffectCreateItem2(uint32 i
)
2658 // special case: generate using spell_loot_template
2659 if(!m_spellInfo
->EffectItemType
[i
])
2661 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2664 // create some random items
2665 ((Player
*)m_caster
)->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
2668 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2671 void Spell::EffectPersistentAA(uint32 i
)
2673 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2675 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2676 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2678 int32 duration
= GetSpellDuration(m_spellInfo
);
2679 DynamicObject
* dynObj
= new DynamicObject
;
2680 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
))
2685 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2686 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2687 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2688 m_caster
->AddDynObject(dynObj
);
2689 dynObj
->GetMap()->Add(dynObj
);
2692 void Spell::EffectEnergize(uint32 i
)
2696 if(!unitTarget
->isAlive())
2699 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2702 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2704 // Some level depends spells
2707 switch (m_spellInfo
->Id
)
2711 level_diff
= m_caster
->getLevel() - 40;
2716 level_diff
= m_caster
->getLevel() - 60;
2721 level_diff
= m_caster
->getLevel() - 60;
2729 damage
-= multiplier
* level_diff
;
2734 if(unitTarget
->GetMaxPower(power
) == 0)
2737 unitTarget
->ModifyPower(power
,damage
);
2738 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2740 // Mad Alchemist's Potion
2741 if (m_spellInfo
->Id
== 45051)
2743 // find elixirs on target
2744 uint32 elixir_mask
= 0;
2745 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2746 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2748 uint32 spell_id
= itr
->second
->GetId();
2749 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2750 elixir_mask
|= mask
;
2753 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2754 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2756 // get all available elixirs by mask and spell level
2757 std::vector
<uint32
> elixirs
;
2758 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2759 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2761 if (itr
->second
& elixir_mask
)
2763 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2766 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2767 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2770 elixirs
.push_back(itr
->first
);
2774 if (!elixirs
.empty())
2776 // cast random elixir on target
2777 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2778 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2783 void Spell::EffectEnergisePct(uint32 i
)
2787 if(!unitTarget
->isAlive())
2790 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2793 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2795 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2799 uint32 gain
= damage
* maxPower
/ 100;
2800 unitTarget
->ModifyPower(power
, gain
);
2801 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2804 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2806 Player
* player
= (Player
*)m_caster
;
2812 if (Script
->GOHello(player
, gameObjTarget
))
2815 switch (gameObjTarget
->GetGoType())
2817 case GAMEOBJECT_TYPE_DOOR
:
2818 case GAMEOBJECT_TYPE_BUTTON
:
2819 gameObjTarget
->UseDoorOrButton();
2820 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2823 case GAMEOBJECT_TYPE_QUESTGIVER
:
2824 // start or end quest
2825 player
->PrepareQuestMenu(guid
);
2826 player
->SendPreparedQuest(guid
);
2829 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2830 // triggering linked GO
2831 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2832 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2835 case GAMEOBJECT_TYPE_GOOBER
:
2836 // goober_scripts can be triggered if the player don't have the quest
2837 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2839 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2840 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2843 // cast goober spell
2844 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2845 ///Quest require to be active for GO using
2846 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2849 gameObjTarget
->AddUniqueUse(player
);
2850 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2852 //TODO? Objective counting called without spell check but with quest objective check
2853 // if send spell id then this line will duplicate to spell casting call (double counting)
2854 // So we or have this line and not required in quest_template have reqSpellIdN
2855 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2856 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2858 // triggering linked GO
2859 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2860 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2864 case GAMEOBJECT_TYPE_CHEST
:
2865 // TODO: possible must be moved to loot release (in different from linked triggering)
2866 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2868 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2869 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2872 // triggering linked GO
2873 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2874 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2876 // Don't return, let loots been taken
2881 player
->SendLoot(guid
, loottype
);
2884 void Spell::EffectOpenLock(uint32
/*i*/)
2886 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2888 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2892 Player
* player
= (Player
*)m_caster
;
2894 LootType loottype
= LOOT_CORPSE
;
2901 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2902 // Arathi Basin banner opening !
2903 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2904 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2906 //isAllowUseBattleGroundObject() already called in CanCast()
2907 // in battleground check
2908 if(BattleGround
*bg
= player
->GetBattleGround())
2910 // check if it's correct bg
2911 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2912 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2916 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2918 //isAllowUseBattleGroundObject() already called in CanCast()
2919 // in battleground check
2920 if(BattleGround
*bg
= player
->GetBattleGround())
2922 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2923 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2927 lockId
= gameObjTarget
->GetLockId();
2928 guid
= gameObjTarget
->GetGUID();
2932 lockId
= itemTarget
->GetProto()->LockID
;
2933 guid
= itemTarget
->GetGUID();
2937 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2941 if(!lockId
) // possible case for GO and maybe for items.
2943 SendLoot(guid
, loottype
);
2948 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2952 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2953 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2954 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2959 for(int i
= 0; i
< 8; ++i
)
2961 // Type==1 This means lockInfo->Index[i] is an item
2962 if(lockInfo
->Type
[i
]==LOCK_KEY_ITEM
&& lockInfo
->Index
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->Index
[i
])
2964 SendLoot(guid
, loottype
);
2970 // Check and skill-up skill
2971 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
2972 SkillId
= m_spellInfo
->EffectMiscValue
[1];
2973 // pickpocketing spells
2974 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
2975 SkillId
= SKILL_LOCKPICKING
;
2977 // skill bonus provided by casting spell (mostly item spells)
2978 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
2980 uint32 reqSkillValue
= lockInfo
->Skill
[0];
2982 if(lockInfo
->Skill
[1]) // required pick lock skill applying
2984 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
2986 SendCastResult(SPELL_FAILED_FIZZLE
);
2990 reqSkillValue
= lockInfo
->Skill
[1];
2992 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
2994 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
3000 loottype
= LOOT_SKINNING
;
3001 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
3003 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
3007 // update skill if really known
3008 if(uint32 SkillValue
= player
->GetPureSkillValue(SkillId
))
3012 // Allow one skill-up until respawned
3013 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3014 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
3015 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3020 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
3025 SendLoot(guid
, loottype
);
3028 void Spell::EffectSummonChangeItem(uint32 i
)
3030 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3033 Player
*player
= (Player
*)m_caster
;
3035 // applied only to using item
3039 // ... only to item in own inventory/bank/equip_slot
3040 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3043 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3047 uint16 pos
= m_CastItem
->GetPos();
3049 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3053 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3055 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3056 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3059 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3061 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3062 player
->DurabilityLoss(pNewItem
, loosePercent
);
3065 if( player
->IsInventoryPos( pos
) )
3067 ItemPosCountVec dest
;
3068 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3069 if( msg
== EQUIP_ERR_OK
)
3071 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3073 // prevent crash at access and unexpected charges counting with item update queue corrupt
3074 if(m_CastItem
==m_targets
.getItemTarget())
3075 m_targets
.setItemTarget(NULL
);
3079 player
->StoreItem( dest
, pNewItem
, true);
3083 else if( player
->IsBankPos ( pos
) )
3085 ItemPosCountVec dest
;
3086 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3087 if( msg
== EQUIP_ERR_OK
)
3089 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3091 // prevent crash at access and unexpected charges counting with item update queue corrupt
3092 if(m_CastItem
==m_targets
.getItemTarget())
3093 m_targets
.setItemTarget(NULL
);
3097 player
->BankItem( dest
, pNewItem
, true);
3101 else if( player
->IsEquipmentPos ( pos
) )
3104 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3105 if( msg
== EQUIP_ERR_OK
)
3107 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3109 // prevent crash at access and unexpected charges counting with item update queue corrupt
3110 if(m_CastItem
==m_targets
.getItemTarget())
3111 m_targets
.setItemTarget(NULL
);
3115 player
->EquipItem( dest
, pNewItem
, true);
3116 player
->AutoUnequipOffhandIfNeed();
3125 void Spell::EffectOpenSecretSafe(uint32 i
)
3127 EffectOpenLock(i
); //no difference for now
3130 void Spell::EffectProficiency(uint32
/*i*/)
3132 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3134 Player
*p_target
= (Player
*)unitTarget
;
3136 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3137 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3139 p_target
->AddWeaponProficiency(subClassMask
);
3140 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3142 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3144 p_target
->AddArmorProficiency(subClassMask
);
3145 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3149 void Spell::EffectApplyAreaAura(uint32 i
)
3153 if(!unitTarget
->isAlive())
3156 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3157 unitTarget
->AddAura(Aur
);
3160 void Spell::EffectSummonType(uint32 i
)
3162 switch(m_spellInfo
->EffectMiscValueB
[i
])
3164 case SUMMON_TYPE_GUARDIAN
:
3165 case SUMMON_TYPE_POSESSED
:
3166 case SUMMON_TYPE_POSESSED2
:
3167 case SUMMON_TYPE_FORCE_OF_NATURE
:
3168 case SUMMON_TYPE_GUARDIAN2
:
3169 EffectSummonGuardian(i
);
3171 case SUMMON_TYPE_WILD
:
3172 EffectSummonWild(i
);
3174 case SUMMON_TYPE_DEMON
:
3175 EffectSummonDemon(i
);
3177 case SUMMON_TYPE_SUMMON
:
3180 case SUMMON_TYPE_CRITTER
:
3181 case SUMMON_TYPE_CRITTER2
:
3182 case SUMMON_TYPE_CRITTER3
:
3183 EffectSummonCritter(i
);
3185 case SUMMON_TYPE_TOTEM_SLOT1
:
3186 case SUMMON_TYPE_TOTEM_SLOT2
:
3187 case SUMMON_TYPE_TOTEM_SLOT3
:
3188 case SUMMON_TYPE_TOTEM_SLOT4
:
3189 case SUMMON_TYPE_TOTEM
:
3190 EffectSummonTotem(i
);
3192 case SUMMON_TYPE_UNKNOWN1
:
3193 case SUMMON_TYPE_UNKNOWN2
:
3194 case SUMMON_TYPE_UNKNOWN3
:
3195 case SUMMON_TYPE_UNKNOWN4
:
3196 case SUMMON_TYPE_UNKNOWN5
:
3199 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3204 void Spell::EffectSummon(uint32 i
)
3206 if(m_caster
->GetPetGUID())
3211 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3214 uint32 level
= m_caster
->getLevel();
3215 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3217 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3219 // set timer for unsummon
3220 int32 duration
= GetSpellDuration(m_spellInfo
);
3222 spawnCreature
->SetDuration(duration
);
3227 Map
*map
= m_caster
->GetMap();
3228 uint32 pet_number
= objmgr
.GeneratePetNumber();
3229 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_caster
->GetPhaseMask(),
3230 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3232 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3233 delete spawnCreature
;
3237 // Summon in dest location
3239 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3241 x
= m_targets
.m_destX
;
3242 y
= m_targets
.m_destY
;
3243 z
= m_targets
.m_destZ
;
3246 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3248 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3250 if(!spawnCreature
->IsPositionValid())
3252 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3253 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3254 delete spawnCreature
;
3258 // set timer for unsummon
3259 int32 duration
= GetSpellDuration(m_spellInfo
);
3261 spawnCreature
->SetDuration(duration
);
3263 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3264 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3265 spawnCreature
->setPowerType(POWER_MANA
);
3266 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3267 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3268 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3269 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3270 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3271 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3272 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3273 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3274 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3276 spawnCreature
->InitStatsForLevel(level
);
3278 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3280 spawnCreature
->AIM_Initialize();
3281 spawnCreature
->InitPetCreateSpells();
3282 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3283 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3285 std::string name
= m_caster
->GetName();
3286 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3287 spawnCreature
->SetName( name
);
3289 map
->Add((Creature
*)spawnCreature
);
3291 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3293 m_caster
->SetPet(spawnCreature
);
3294 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3295 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3296 ((Player
*)m_caster
)->PetSpellInitialize();
3300 void Spell::EffectLearnSpell(uint32 i
)
3305 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3307 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3308 EffectLearnPetSpell(i
);
3313 Player
*player
= (Player
*)unitTarget
;
3315 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3316 player
->learnSpell(spellToLearn
,false);
3318 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3321 void Spell::EffectDispel(uint32 i
)
3326 // Fill possible dispell list
3327 std::vector
<Aura
*> dispel_list
;
3329 // Create dispel mask by dispel type
3330 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3331 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3332 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3333 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3335 Aura
*aur
= (*itr
).second
;
3336 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3338 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3340 bool positive
= true;
3341 if (!aur
->IsPositive())
3344 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3346 // do not remove positive auras if friendly target
3347 // negative auras if non-friendly target
3348 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3351 // Add aura to dispel list
3352 dispel_list
.push_back(aur
);
3355 // Ok if exist some buffs for dispel try dispel it
3356 if (!dispel_list
.empty())
3358 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3359 std::list
< uint32
> fail_list
; // spell_id
3360 int32 list_size
= dispel_list
.size();
3361 // Dispell N = damage buffs (or while exist buffs for dispel)
3362 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3364 // Random select buff for dispel
3365 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3367 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3368 // Base dispel chance
3369 // TODO: possible chance depend from spell level??
3370 int32 miss_chance
= 0;
3371 // Apply dispel mod from aura caster
3372 if (Unit
*caster
= aur
->GetCaster())
3374 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3375 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3378 if (roll_chance_i(miss_chance
))
3379 fail_list
.push_back(aur
->GetId());
3381 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3382 // Remove buff from list for prevent doubles
3383 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3385 Aura
*dispeled
= *j
;
3386 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3388 j
= dispel_list
.erase(j
);
3395 // Send success log and really remove auras
3396 if (!success_list
.empty())
3398 int32 count
= success_list
.size();
3399 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3400 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3401 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3402 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3403 data
<< uint8(0); // not used
3404 data
<< uint32(count
); // count
3405 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3407 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3408 data
<< uint32(spellInfo
->Id
); // Spell Id
3409 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3410 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3412 m_caster
->SendMessageToSet(&data
, true);
3416 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3418 uint32 heal_spell
= 0;
3419 switch (m_spellInfo
->Id
)
3421 case 19505: heal_spell
= 19658; break;
3422 case 19731: heal_spell
= 19732; break;
3423 case 19734: heal_spell
= 19733; break;
3424 case 19736: heal_spell
= 19735; break;
3425 case 27276: heal_spell
= 27278; break;
3426 case 27277: heal_spell
= 27279; break;
3428 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3432 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3435 // Send fail log to client
3436 if (!fail_list
.empty())
3438 // Failed to dispell
3439 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3440 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3441 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3442 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3443 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3444 data
<< uint32(*j
); // Spell Id
3445 m_caster
->SendMessageToSet(&data
, true);
3450 void Spell::EffectDualWield(uint32
/*i*/)
3452 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3453 ((Player
*)unitTarget
)->SetCanDualWield(true);
3456 void Spell::EffectPull(uint32
/*i*/)
3458 // TODO: create a proper pull towards distract spell center for distract
3459 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3462 void Spell::EffectDistract(uint32
/*i*/)
3464 // Check for possible target
3465 if (!unitTarget
|| unitTarget
->isInCombat())
3468 // target must be OK to do this
3469 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3472 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3474 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3476 // For players just turn them
3478 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3479 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3480 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3484 // Set creature Distracted, Stop it, And turn it
3485 unitTarget
->SetOrientation(angle
);
3486 unitTarget
->StopMoving();
3487 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3491 void Spell::EffectPickPocket(uint32
/*i*/)
3493 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3496 // victim must be creature and attackable
3497 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3500 // victim have to be alive and humanoid or undead
3501 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3503 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3505 if (chance
> irand(0, 19))
3507 // Stealing successful
3508 //sLog.outDebug("Sending loot from pickpocket");
3509 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3513 // Reveal action + get attack
3514 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3515 if (((Creature
*)unitTarget
)->AI())
3516 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3521 void Spell::EffectAddFarsight(uint32 i
)
3523 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3524 int32 duration
= GetSpellDuration(m_spellInfo
);
3525 DynamicObject
* dynObj
= new DynamicObject
;
3526 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
))
3531 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3532 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3533 m_caster
->AddDynObject(dynObj
);
3534 dynObj
->GetMap()->Add(dynObj
);
3535 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3536 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3539 void Spell::EffectSummonWild(uint32 i
)
3541 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3545 uint32 level
= m_caster
->getLevel();
3547 // level of creature summoned using engineering item based at engineering skill level
3548 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3550 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3551 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3553 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3561 // select center of summon position
3562 float center_x
= m_targets
.m_destX
;
3563 float center_y
= m_targets
.m_destY
;
3564 float center_z
= m_targets
.m_destZ
;
3566 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3568 int32 amount
= damage
> 0 ? damage
: 1;
3570 for(int32 count
= 0; count
< amount
; ++count
)
3573 // If dest location if present
3574 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3576 // Summon 1 unit in dest location
3579 px
= m_targets
.m_destX
;
3580 py
= m_targets
.m_destY
;
3581 pz
= m_targets
.m_destZ
;
3583 // Summon in random point all other units if location present
3585 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3587 // Summon if dest location not present near caster
3589 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3591 int32 duration
= GetSpellDuration(m_spellInfo
);
3593 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3595 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3599 void Spell::EffectSummonGuardian(uint32 i
)
3601 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3605 // Jewelery statue case (totem like)
3606 if(m_spellInfo
->SpellIconID
==2056)
3608 EffectSummonTotem(i
);
3612 // set timer for unsummon
3613 int32 duration
= GetSpellDuration(m_spellInfo
);
3615 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3616 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3617 // so this code hack in fact
3618 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3619 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3620 return; // find old guardian, ignore summon
3622 // in another case summon new
3623 uint32 level
= m_caster
->getLevel();
3625 // level of pet summoned using engineering item based at engineering skill level
3626 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3628 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3629 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3631 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3639 // select center of summon position
3640 float center_x
= m_targets
.m_destX
;
3641 float center_y
= m_targets
.m_destY
;
3642 float center_z
= m_targets
.m_destZ
;
3644 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3646 int32 amount
= damage
> 0 ? damage
: 1;
3648 for(int32 count
= 0; count
< amount
; ++count
)
3650 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3652 Map
*map
= m_caster
->GetMap();
3653 uint32 pet_number
= objmgr
.GeneratePetNumber();
3654 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3655 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3657 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3658 delete spawnCreature
;
3663 // If dest location if present
3664 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3666 // Summon 1 unit in dest location
3669 px
= m_targets
.m_destX
;
3670 py
= m_targets
.m_destY
;
3671 pz
= m_targets
.m_destZ
;
3673 // Summon in random point all other units if location present
3675 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3677 // Summon if dest location not present near caster
3679 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3681 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3683 if(!spawnCreature
->IsPositionValid())
3685 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3686 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3687 delete spawnCreature
;
3692 spawnCreature
->SetDuration(duration
);
3694 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3695 spawnCreature
->setPowerType(POWER_MANA
);
3696 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3697 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3698 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3699 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3700 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3701 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3702 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3704 spawnCreature
->InitStatsForLevel(level
);
3705 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3707 spawnCreature
->AIM_Initialize();
3709 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3710 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3712 map
->Add((Creature
*)spawnCreature
);
3716 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3721 if(unitTarget
->isInFlight())
3724 uint32 mapid
= m_caster
->GetMapId();
3725 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3728 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3730 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3731 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, -m_caster
->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
3733 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3736 void Spell::EffectLearnSkill(uint32 i
)
3738 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3744 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3745 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3746 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3749 void Spell::EffectAddHonor(uint32
/*i*/)
3751 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3754 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3756 // TODO: find formula for honor reward based on player's level!
3758 // now fixed only for level 70 players:
3759 if (((Player
*)unitTarget
)->getLevel() == 70)
3760 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3763 void Spell::EffectTradeSkill(uint32
/*i*/)
3765 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3767 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3768 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3769 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3772 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3774 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3779 Player
* p_caster
= (Player
*)m_caster
;
3781 // not grow at item use at item case
3782 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3784 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3788 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3792 // item can be in trade slot and have owner diff. from caster
3793 Player
* item_owner
= itemTarget
->GetOwner();
3797 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3799 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3800 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3801 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3802 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3805 // remove old enchanting before applying new if equipped
3806 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3808 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3810 // add new enchanting if equipped
3811 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3814 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3816 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3821 Player
* p_caster
= (Player
*)m_caster
;
3823 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3827 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3831 // support only enchantings with add socket in this slot
3833 bool add_socket
= false;
3834 for(int i
= 0; i
< 3; ++i
)
3836 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3844 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.",
3845 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3850 // item can be in trade slot and have owner diff. from caster
3851 Player
* item_owner
= itemTarget
->GetOwner();
3855 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3857 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3858 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3859 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3860 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3863 // remove old enchanting before applying new if equipped
3864 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3866 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3868 // add new enchanting if equipped
3869 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3872 void Spell::EffectEnchantItemTmp(uint32 i
)
3874 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3877 Player
* p_caster
= (Player
*)m_caster
;
3882 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3884 // Shaman Rockbiter Weapon
3885 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3887 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3889 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3890 // with already applied percent bonus from Elemental Weapons talent
3891 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3892 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3893 switch(enchnting_damage
)
3896 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3898 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3899 case 5: enchant_id
= 3025; break; // 20%
3901 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3902 case 7: enchant_id
= 3027; break; // 20%
3904 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3905 case 10: enchant_id
= 503; break; // 14%
3906 case 11: enchant_id
= 3031; break; // 20%
3908 case 15: enchant_id
= 3035; break; // 0%
3909 case 16: enchant_id
= 1663; break; // 7%
3910 case 17: enchant_id
= 3033; break; // 14%
3911 case 18: enchant_id
= 3034; break; // 20%
3913 case 28: enchant_id
= 3038; break; // 0%
3914 case 29: enchant_id
= 683; break; // 7%
3915 case 31: enchant_id
= 3036; break; // 14%
3916 case 33: enchant_id
= 3037; break; // 20%
3918 case 40: enchant_id
= 3041; break; // 0%
3919 case 42: enchant_id
= 1664; break; // 7%
3920 case 45: enchant_id
= 3039; break; // 14%
3921 case 48: enchant_id
= 3040; break; // 20%
3923 case 49: enchant_id
= 3044; break; // 0%
3924 case 52: enchant_id
= 2632; break; // 7%
3925 case 55: enchant_id
= 3042; break; // 14%
3926 case 58: enchant_id
= 3043; break; // 20%
3928 case 62: enchant_id
= 2633; break; // 0%
3929 case 66: enchant_id
= 3018; break; // 7%
3930 case 70: enchant_id
= 3019; break; // 14%
3931 case 74: enchant_id
= 3020; break; // 20%
3933 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3940 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3944 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3947 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3951 // select enchantment duration
3954 // rogue family enchantments exception by duration
3955 if(m_spellInfo
->Id
==38615)
3956 duration
= 1800; // 30 mins
3957 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3958 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3959 duration
= 3600; // 1 hour
3960 // shaman family enchantments
3961 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3962 duration
= 1800; // 30 mins
3963 // other cases with this SpellVisual already selected
3964 else if(m_spellInfo
->SpellVisual
[0]==215)
3965 duration
= 1800; // 30 mins
3966 // some fishing pole bonuses
3967 else if(m_spellInfo
->SpellVisual
[0]==563)
3968 duration
= 600; // 10 mins
3969 // shaman rockbiter enchantments
3970 else if(m_spellInfo
->SpellVisual
[0]==0)
3971 duration
= 1800; // 30 mins
3972 else if(m_spellInfo
->Id
==29702)
3973 duration
= 300; // 5 mins
3974 else if(m_spellInfo
->Id
==37360)
3975 duration
= 300; // 5 mins
3978 duration
= 3600; // 1 hour
3980 // item can be in trade slot and have owner diff. from caster
3981 Player
* item_owner
= itemTarget
->GetOwner();
3985 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3987 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3988 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3989 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3990 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3993 // remove old enchanting before applying new if equipped
3994 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3996 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3998 // add new enchanting if equipped
3999 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
4002 void Spell::EffectTameCreature(uint32
/*i*/)
4004 if(m_caster
->GetPetGUID())
4010 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4013 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4015 if(creatureTarget
->isPet())
4018 if(m_caster
->getClass() != CLASS_HUNTER
)
4021 // cast finish successfully
4022 //SendChannelUpdate(0);
4025 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4027 // kill original creature
4028 creatureTarget
->setDeathState(JUST_DIED
);
4029 creatureTarget
->RemoveCorpse();
4030 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4032 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4034 // prepare visual effect for levelup
4035 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4038 pet
->GetMap()->Add((Creature
*)pet
);
4040 // visual effect for levelup
4041 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4043 // caster have pet now
4044 m_caster
->SetPet(pet
);
4046 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4048 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4049 ((Player
*)m_caster
)->PetSpellInitialize();
4053 void Spell::EffectSummonPet(uint32 i
)
4055 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4057 Pet
*OldSummon
= m_caster
->GetPet();
4059 // if pet requested type already exist
4062 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4064 // pet in corpse state can't be summoned
4065 if( OldSummon
->isDead() )
4068 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4069 OldSummon
->SetMapId(m_caster
->GetMapId());
4072 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4074 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4075 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4077 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4079 ((Player
*)m_caster
)->PetSpellInitialize();
4084 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4085 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4090 Pet
* NewSummon
= new Pet
;
4092 // petentry==0 for hunter "call pet" (current pet summoned if any)
4093 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4095 if(NewSummon
->getPetType()==SUMMON_PET
)
4097 // Remove Demonic Sacrifice auras (known pet)
4098 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4099 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4101 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4103 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4104 itr
= auraClassScripts
.begin();
4114 // not error in case fail hunter call pet
4121 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4125 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4130 Map
*map
= m_caster
->GetMap();
4131 uint32 pet_number
= objmgr
.GeneratePetNumber();
4132 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4133 petentry
, pet_number
))
4140 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4142 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4144 if(!NewSummon
->IsPositionValid())
4146 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4147 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4152 uint32 petlevel
= m_caster
->getLevel();
4153 NewSummon
->setPetType(SUMMON_PET
);
4155 uint32 faction
= m_caster
->getFaction();
4156 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4158 if ( ((Creature
*)m_caster
)->isTotem() )
4159 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4161 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4164 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4165 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4166 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4167 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4168 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4169 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4170 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4171 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4172 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4173 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4175 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4176 // this enables pet details window (Shift+P)
4178 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4179 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4180 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4182 NewSummon
->InitStatsForLevel(petlevel
);
4183 NewSummon
->InitPetCreateSpells();
4184 NewSummon
->InitTalentForLevel();
4186 if(NewSummon
->getPetType()==SUMMON_PET
)
4188 // Remove Demonic Sacrifice auras (new pet)
4189 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4190 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4192 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4194 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4195 itr
= auraClassScripts
.begin();
4201 // generate new name for summon pet
4202 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4203 if(!new_name
.empty())
4204 NewSummon
->SetName(new_name
);
4206 else if(NewSummon
->getPetType()==HUNTER_PET
)
4207 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4209 NewSummon
->AIM_Initialize();
4210 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4211 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4213 map
->Add((Creature
*)NewSummon
);
4215 m_caster
->SetPet(NewSummon
);
4216 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4218 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4220 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4221 ((Player
*)m_caster
)->PetSpellInitialize();
4225 void Spell::EffectLearnPetSpell(uint32 i
)
4227 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4230 Player
*_player
= (Player
*)m_caster
;
4232 Pet
*pet
= _player
->GetPet();
4238 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4239 if(!learn_spellproto
)
4242 pet
->learnSpell(learn_spellproto
->Id
);
4244 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4245 _player
->PetSpellInitialize();
4248 void Spell::EffectTaunt(uint32
/*i*/)
4250 // this effect use before aura Taunt apply for prevent taunt already attacking target
4251 // for spell as marked "non effective at already attacking target"
4252 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4254 if(unitTarget
->getVictim()==m_caster
)
4256 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4261 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4262 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4263 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4266 void Spell::EffectWeaponDmg(uint32 i
)
4270 if(!unitTarget
->isAlive())
4273 // multiple weapon dmg effect workaround
4274 // execute only the last weapon damage
4275 // and handle all effects at once
4276 for (int j
= 0; j
< 3; j
++)
4278 switch(m_spellInfo
->Effect
[j
])
4280 case SPELL_EFFECT_WEAPON_DAMAGE
:
4281 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4282 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4283 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4284 if (j
< i
) // we must calculate only at last weapon effect
4290 // some spell specific modifiers
4291 bool customBonusDamagePercentMod
= false;
4292 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4293 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4294 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4295 bool normalized
= false;
4297 int32 spell_bonus
= 0; // bonus specific for spell
4298 switch(m_spellInfo
->SpellFamilyName
)
4300 case SPELLFAMILY_WARRIOR
:
4302 // Whirlwind, single only spell with 2 weapon white damage apply if have
4303 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4305 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4306 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4308 // Devastate bonus and sunder armor refresh
4309 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4312 // Need refresh all Sunder Armor auras from this caster
4313 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4314 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4316 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4317 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4318 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4319 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4321 (*itr
).second
->RefreshAura();
4322 stack
= (*itr
).second
->GetStackAmount();
4326 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4330 case SPELLFAMILY_ROGUE
:
4333 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4335 customBonusDamagePercentMod
= true;
4336 bonusDamagePercentMod
= 2.5f
; // 250%
4338 // Mutilate (for each hand)
4339 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4343 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4348 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4349 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4351 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4360 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4364 case SPELLFAMILY_PALADIN
:
4366 // Seal of Command - receive benefit from Spell Damage and Healing
4367 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4369 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4370 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4374 case SPELLFAMILY_SHAMAN
:
4376 // Skyshatter Harness item set bonus
4378 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4380 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4381 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4383 // Stormstrike AP Buff
4384 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4386 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4394 int32 fixed_bonus
= 0;
4395 for (int j
= 0; j
< 3; j
++)
4397 switch(m_spellInfo
->Effect
[j
])
4399 case SPELL_EFFECT_WEAPON_DAMAGE
:
4400 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4401 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4403 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4404 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4407 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4408 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4410 // applied only to prev.effects fixed damage
4411 if(customBonusDamagePercentMod
)
4412 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4414 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4417 break; // not weapon damage effect, just skip
4421 // non-weapon damage
4422 int32 bonus
= spell_bonus
+ fixed_bonus
;
4424 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4428 switch(m_attackType
)
4431 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4432 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4433 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4436 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4437 bonus
= int32(bonus
*weapon_total_pct
);
4440 // + weapon damage with applied weapon% dmg to base weapon damage in call
4441 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4444 bonus
= int32(bonus
*totalDamagePercentMod
);
4446 // prevent negative damage
4447 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4449 // Add melee damage bonuses (also check for negative)
4450 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4451 m_damage
+= eff_damage
;
4454 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4456 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4457 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4461 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4463 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4464 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4468 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4470 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4472 // wands don't have ammo
4473 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4476 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4478 if(pItem
->GetMaxStackCount()==1)
4480 // decrease durability for non-stackable throw weapon
4481 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4485 // decrease items amount for stackable throw weapon
4487 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4490 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4491 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4495 void Spell::EffectThreat(uint32
/*i*/)
4497 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4500 if(!unitTarget
->CanHaveThreatList())
4503 unitTarget
->AddThreat(m_caster
, float(damage
));
4506 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4510 if(!unitTarget
->isAlive())
4513 uint32 heal
= m_caster
->GetMaxHealth();
4518 void Spell::EffectInterruptCast(uint32
/*i*/)
4522 if(!unitTarget
->isAlive())
4525 // TODO: not all spells that used this effect apply cooldown at school spells
4526 // also exist case: apply cooldown to interrupted cast only and to all spells
4527 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4529 if (unitTarget
->m_currentSpells
[i
])
4531 // check if we can interrupt spell
4532 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4534 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4535 unitTarget
->InterruptSpell(i
,false);
4541 void Spell::EffectSummonObjectWild(uint32 i
)
4543 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4545 GameObject
* pGameObj
= new GameObject
;
4547 WorldObject
* target
= focusObject
;
4552 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4554 x
= m_targets
.m_destX
;
4555 y
= m_targets
.m_destY
;
4556 z
= m_targets
.m_destZ
;
4559 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4561 Map
*map
= target
->GetMap();
4563 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4564 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4570 int32 duration
= GetSpellDuration(m_spellInfo
);
4571 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4572 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4574 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4575 m_caster
->AddGameObject(pGameObj
);
4578 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4580 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4582 Player
*pl
= (Player
*)m_caster
;
4583 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4584 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4586 uint32 team
= ALLIANCE
;
4588 if(pl
->GetTeam() == team
)
4591 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4596 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4598 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4600 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4601 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4603 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4608 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4610 GameObject
* linkedGO
= new GameObject
;
4611 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4612 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4614 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4615 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4617 m_caster
->AddGameObject(linkedGO
);
4629 void Spell::EffectScriptEffect(uint32 effIndex
)
4631 // TODO: we must implement hunter pet summon at login there (spell 6962)
4633 switch(m_spellInfo
->SpellFamilyName
)
4635 case SPELLFAMILY_GENERIC
:
4637 switch(m_spellInfo
->Id
)
4639 // PX-238 Winter Wondervolt TRAP
4642 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4645 for(int j
= 0; j
< 4; ++j
)
4646 if(unitTarget
->HasAura(spells
[j
],0))
4650 uint32 iTmpSpellId
= spells
[urand(0,3)];
4653 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4659 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4662 uint32 spell_id
= 0;
4665 case 1: spell_id
= 8854; break;
4666 default: spell_id
= 8855; break;
4669 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4672 // Brittle Armor - need remove one 24575 Brittle Armor aura
4674 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4676 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4678 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4680 // Orb teleport spells
4694 switch(m_spellInfo
->Id
)
4696 case 25140: spellid
= 32571; break;
4697 case 25143: spellid
= 32572; break;
4698 case 25650: spellid
= 30140; break;
4699 case 25652: spellid
= 30141; break;
4700 case 29128: spellid
= 32568; break;
4701 case 29129: spellid
= 32569; break;
4702 case 35376: spellid
= 25649; break;
4703 case 35727: spellid
= 35730; break;
4708 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4711 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4726 if(!unitTarget
|| !unitTarget
->isAlive())
4729 // Onyxia Scale Cloak
4730 if(unitTarget
->GetDummyAura(22683))
4734 m_caster
->CastSpell(unitTarget
, 22682, true);
4737 // Summon Black Qiraji Battle Tank
4743 // Prevent stacking of mounts
4744 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4746 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4747 if (unitTarget
->GetAreaId() == 3428)
4748 unitTarget
->CastSpell(unitTarget
, 25863, false);
4750 unitTarget
->CastSpell(unitTarget
, 26655, false);
4753 // Piccolo of the Flaming Fire
4756 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4758 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4761 // Mirren's Drinking Hat
4765 switch ( urand(1,6) )
4767 case 1:case 2:case 3:
4768 item
= 23584;break; // Loch Modan Lager
4770 item
= 23585;break; // Stouthammer Lite
4772 item
= 23586;break; // Aerie Peak Pale Ale
4775 DoCreateItem(effIndex
,item
);
4781 // Removes snares and roots.
4782 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4783 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4784 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4788 Aura
*aur
= iter
->second
;
4789 if (!aur
->IsPositive()) //only remove negative spells
4791 // check for mechanic mask
4792 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4794 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4798 next
= Auras
.begin();
4810 unitTarget
->CastSpell(unitTarget
, 41131, true);
4813 // Force Cast - Portal Effect: Sunwell Isle
4819 unitTarget
->CastSpell(unitTarget
, 44870, true);
4822 // Goblin Weather Machine
4831 case 0: spellId
= 46740; break;
4832 case 1: spellId
= 46739; break;
4833 case 2: spellId
= 46738; break;
4834 case 3: spellId
= 46736; break;
4836 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4842 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4845 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4849 // Emblazon Runeblade
4855 unitTarget
->CastSpell(unitTarget
,51771,false);
4861 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4863 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4864 unitTarget
->CastSpell(unitTarget
, damage
, false);
4867 // random spell learn instead placeholder
4868 case 60893: // Northrend Alchemy Research
4869 case 61177: // Northrend Inscription Research
4870 case 61288: // Minor Inscription Research
4871 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4873 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4875 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4879 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4881 Player
* player
= (Player
*)m_caster
;
4883 // need replace effect 0 item by loot
4884 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4886 if(!player
->HasItemCount(reagent_id
,1))
4891 player
->DestroyItemCount (reagent_id
,count
,true);
4893 // create some random items
4894 player
->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
4896 // learn random explicit discovery recipe (if any)
4897 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4898 player
->learnSpell(discoveredSpell
,false);
4904 case SPELLFAMILY_WARLOCK
:
4906 switch(m_spellInfo
->Id
)
4908 // Healthstone creating spells
4920 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4921 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4923 if((*i
)->GetId() == 18692)
4928 else if((*i
)->GetId() == 18693)
4935 static uint32
const itypes
[8][3] = {
4936 { 5512,19004,19005}, // Minor Healthstone
4937 { 5511,19006,19007}, // Lesser Healthstone
4938 { 5509,19008,19009}, // Healthstone
4939 { 5510,19010,19011}, // Greater Healthstone
4940 { 9421,19012,19013}, // Major Healthstone
4941 {22103,22104,22105}, // Master Healthstone
4942 {36889,36890,36891}, // Demonic Healthstone
4943 {36892,36893,36894} // Fel Healthstone
4946 switch(m_spellInfo
->Id
)
4949 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4951 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4953 itemtype
=itypes
[2][rank
];break; // Healthstone
4955 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4957 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4959 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4961 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4963 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4967 DoCreateItem( effIndex
, itemtype
);
4973 case SPELLFAMILY_PRIEST
:
4975 switch(m_spellInfo
->Id
)
4977 // Pain and Suffering
4982 // Refresh Shadow Word: Pain on target
4983 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
4984 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
4986 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4987 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
4988 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
4989 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4991 (*itr
).second
->RefreshAura();
5002 case SPELLFAMILY_HUNTER
:
5004 switch(m_spellInfo
->Id
)
5010 int32 basePoint
= 0;
5011 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5012 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5014 Aura
*aura
= (*i
).second
;
5015 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5017 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5018 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5019 if (!(familyFlag
& 0x000000800000C000LL
))
5021 // Refresh aura duration
5022 aura
->RefreshAura();
5024 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5025 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5027 spellId
= 53353; // 53353 Chimera Shot - Serpent
5028 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5030 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5031 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5033 spellId
= 53358; // 53358 Chimera Shot - Viper
5034 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5036 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5037 if (familyFlag
& 0x0000000000008000LL
)
5038 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5039 // ?? nothing say in spell desc (possibly need addition check)
5040 //if (familyFlag & 0x0000010000000000LL || // dot
5041 // familyFlag & 0x0000100000000000LL) // stun
5043 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5047 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5055 case SPELLFAMILY_PALADIN
:
5058 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5060 if(!unitTarget
|| !unitTarget
->isAlive())
5062 uint32 spellId1
= 0;
5063 uint32 spellId2
= 0;
5065 // Judgement self add switch
5066 switch (m_spellInfo
->Id
)
5068 case 41467: break; // Judgement
5069 case 53407: spellId1
= 20184; break; // Judgement of Justice
5070 case 20271: // Judgement of Light
5071 case 57774: spellId1
= 20185; break; // Judgement of Light
5072 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5076 // all seals have aura dummy in 2 effect
5077 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5078 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5080 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5081 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5082 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5084 spellId2
= (*itr
)->GetModifier()->m_amount
;
5085 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5091 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5093 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5097 case SPELLFAMILY_POTION
:
5099 switch(m_spellInfo
->Id
)
5106 unitTarget
->CastSpell(unitTarget
, 28694, true);
5114 // 25% chance of casting a random buff
5115 if(roll_chance_i(75))
5118 // triggered spells are 28703 to 28707
5119 // Note: some sources say, that there was the possibility of
5120 // receiving a debuff. However, this seems to be removed by a patch.
5121 const uint32 spellid
= 28703;
5123 // don't overwrite an existing aura
5124 for(uint8 i
=0; i
<5; i
++)
5125 if(unitTarget
->HasAura(spellid
+i
, 0))
5127 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5136 // 25% chance of casting Nightmare Pollen
5137 if(roll_chance_i(75))
5139 unitTarget
->CastSpell(unitTarget
, 28721, true);
5147 // normal DB scripted effect
5151 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5152 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5155 void Spell::EffectSanctuary(uint32
/*i*/)
5159 //unitTarget->CombatStop();
5161 unitTarget
->CombatStop();
5162 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5163 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5164 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5166 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5170 void Spell::EffectAddComboPoints(uint32
/*i*/)
5175 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5181 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5184 void Spell::EffectDuel(uint32 i
)
5186 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5189 Player
*caster
= (Player
*)m_caster
;
5190 Player
*target
= (Player
*)unitTarget
;
5192 // caster or target already have requested duel
5193 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5196 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5197 // Don't have to check the target's map since you cannot challenge someone across maps
5198 uint32 mapid
= caster
->GetMapId();
5199 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5201 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5205 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5206 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5208 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5212 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5213 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5215 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5219 //CREATE DUEL FLAG OBJECT
5220 GameObject
* pGameObj
= new GameObject
;
5222 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5224 Map
*map
= m_caster
->GetMap();
5225 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5226 map
, m_caster
->GetPhaseMask(),
5227 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5228 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5229 m_caster
->GetPositionZ(),
5230 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
5236 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5237 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5238 int32 duration
= GetSpellDuration(m_spellInfo
);
5239 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5240 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5242 m_caster
->AddGameObject(pGameObj
);
5247 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5248 data
<< pGameObj
->GetGUID();
5249 data
<< caster
->GetGUID();
5250 caster
->GetSession()->SendPacket(&data
);
5251 target
->GetSession()->SendPacket(&data
);
5254 DuelInfo
*duel
= new DuelInfo
;
5255 duel
->initiator
= caster
;
5256 duel
->opponent
= target
;
5257 duel
->startTime
= 0;
5258 duel
->startTimer
= 0;
5259 caster
->duel
= duel
;
5261 DuelInfo
*duel2
= new DuelInfo
;
5262 duel2
->initiator
= caster
;
5263 duel2
->opponent
= caster
;
5264 duel2
->startTime
= 0;
5265 duel2
->startTimer
= 0;
5266 target
->duel
= duel2
;
5268 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5269 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5272 void Spell::EffectStuck(uint32
/*i*/)
5274 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5277 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5280 Player
* pTarget
= (Player
*)unitTarget
;
5282 sLog
.outDebug("Spell Effect: Stuck");
5283 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());
5285 if(pTarget
->isInFlight())
5288 // homebind location is loaded always
5289 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5291 // Stuck spell trigger Hearthstone cooldown
5292 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5295 Spell
spell(pTarget
,spellInfo
,true,0);
5296 spell
.SendSpellCooldown();
5299 void Spell::EffectSummonPlayer(uint32
/*i*/)
5301 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5304 // Evil Twin (ignore player summon, but hide this for summoner)
5305 if(unitTarget
->GetDummyAura(23445))
5309 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5311 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5313 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5314 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5315 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5316 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5317 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5320 static ScriptInfo
generateActivateCommand()
5323 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5327 void Spell::EffectActivateObject(uint32 effect_idx
)
5332 static ScriptInfo activateCommand
= generateActivateCommand();
5334 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5336 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5339 void Spell::EffectApplyGlyph(uint32 i
)
5341 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5344 Player
*player
= (Player
*)m_caster
;
5347 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5349 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5351 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5352 player
->SetGlyph(m_glyphIndex
, 0);
5357 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5359 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5361 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5363 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5365 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5366 return; // glyph slot missmatch
5370 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5371 player
->SetGlyph(m_glyphIndex
, glyph
);
5376 void Spell::EffectSummonTotem(uint32 i
)
5379 switch(m_spellInfo
->EffectMiscValueB
[i
])
5381 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5382 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5383 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5384 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5385 // Battle standard case
5386 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5387 // jewelery statue case, like totem without slot
5388 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5392 if(slot
< MAX_TOTEM
)
5394 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5397 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5398 if(OldTotem
&& OldTotem
->isTotem())
5399 ((Totem
*)OldTotem
)->UnSummon();
5404 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5405 team
= ((Player
*)m_caster
)->GetTeam();
5407 Totem
* pTotem
= new Totem
;
5409 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5410 m_spellInfo
->EffectMiscValue
[i
], team
))
5416 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5419 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5421 // totem must be at same Z in case swimming caster and etc.
5422 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5423 z
= m_caster
->GetPositionZ();
5425 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5427 if(slot
< MAX_TOTEM
)
5428 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5430 pTotem
->SetOwner(m_caster
->GetGUID());
5431 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5433 int32 duration
=GetSpellDuration(m_spellInfo
);
5434 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5435 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5436 pTotem
->SetDuration(duration
);
5438 if (damage
) // if not spell info, DB values used
5440 pTotem
->SetMaxHealth(damage
);
5441 pTotem
->SetHealth(damage
);
5444 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5446 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5447 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5449 pTotem
->Summon(m_caster
);
5451 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5453 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5454 data
<< uint8(slot
);
5455 data
<< uint64(pTotem
->GetGUID());
5456 data
<< uint32(duration
);
5457 data
<< uint32(m_spellInfo
->Id
);
5458 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5462 void Spell::EffectEnchantHeldItem(uint32 i
)
5464 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5465 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5468 Player
* item_owner
= (Player
*)unitTarget
;
5469 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5475 if(!item
->IsEquipped())
5478 if (m_spellInfo
->EffectMiscValue
[i
])
5480 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5481 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5483 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5485 duration
= 10; //10 seconds for enchants which don't have listed duration
5487 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5491 // Always go to temp enchantment slot
5492 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5494 // Enchantment will not be applied if a different one already exists
5495 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5498 // Apply the temporary enchantment
5499 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5500 item_owner
->ApplyEnchantment(item
,slot
,true);
5504 void Spell::EffectDisEnchant(uint32
/*i*/)
5506 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5509 Player
* p_caster
= (Player
*)m_caster
;
5510 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5513 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5515 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5517 // item will be removed at disenchanting end
5520 void Spell::EffectInebriate(uint32
/*i*/)
5522 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5525 Player
*player
= (Player
*)unitTarget
;
5526 uint16 currentDrunk
= player
->GetDrunkValue();
5527 uint16 drunkMod
= damage
* 256;
5528 if (currentDrunk
+ drunkMod
> 0xFFFF)
5529 currentDrunk
= 0xFFFF;
5531 currentDrunk
+= drunkMod
;
5532 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5535 void Spell::EffectFeedPet(uint32 i
)
5537 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5540 Player
*_player
= (Player
*)m_caster
;
5542 Item
* foodItem
= m_targets
.getItemTarget();
5546 Pet
*pet
= _player
->GetPet();
5553 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5558 _player
->DestroyItemCount(foodItem
,count
,true);
5559 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5561 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5564 void Spell::EffectDismissPet(uint32
/*i*/)
5566 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5569 Pet
* pet
= m_caster
->GetPet();
5571 // not let dismiss dead pet
5572 if(!pet
||!pet
->isAlive())
5575 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5578 void Spell::EffectSummonObject(uint32 i
)
5580 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5583 switch(m_spellInfo
->Effect
[i
])
5585 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5586 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5587 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5588 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5592 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5595 GameObject
* obj
= NULL
;
5597 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5599 if(obj
) obj
->Delete();
5600 m_caster
->m_ObjectSlot
[slot
] = 0;
5603 GameObject
* pGameObj
= new GameObject
;
5605 float rot2
= sin(m_caster
->GetOrientation()/2);
5606 float rot3
= cos(m_caster
->GetOrientation()/2);
5609 // If dest location if present
5610 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5612 x
= m_targets
.m_destX
;
5613 y
= m_targets
.m_destY
;
5614 z
= m_targets
.m_destZ
;
5616 // Summon in random point all other units if location present
5618 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5620 Map
*map
= m_caster
->GetMap();
5621 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5622 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5628 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5629 int32 duration
= GetSpellDuration(m_spellInfo
);
5630 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5631 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5632 m_caster
->AddGameObject(pGameObj
);
5635 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5636 data
<< pGameObj
->GetGUID();
5637 m_caster
->SendMessageToSet(&data
,true);
5639 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5642 void Spell::EffectResurrect(uint32
/*effIndex*/)
5646 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5649 if(unitTarget
->isAlive())
5651 if(!unitTarget
->IsInWorld())
5654 switch (m_spellInfo
->Id
)
5656 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5658 if (roll_chance_i(67))
5660 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5664 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5666 if (roll_chance_i(50))
5668 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5676 Player
* pTarget
= ((Player
*)unitTarget
);
5678 if(pTarget
->isRessurectRequested()) // already have one active request
5681 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5682 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5684 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5685 SendResurrectRequest(pTarget
);
5688 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5690 if(!unitTarget
|| !unitTarget
->isAlive())
5693 if( unitTarget
->m_extraAttacks
)
5696 unitTarget
->m_extraAttacks
= damage
;
5699 void Spell::EffectParry(uint32
/*i*/)
5701 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5702 ((Player
*)unitTarget
)->SetCanParry(true);
5705 void Spell::EffectBlock(uint32
/*i*/)
5707 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5708 ((Player
*)unitTarget
)->SetCanBlock(true);
5711 void Spell::EffectMomentMove(uint32 i
)
5713 if(unitTarget
->isInFlight())
5716 if( m_spellInfo
->rangeIndex
== 1) //self range
5718 uint32 mapid
= m_caster
->GetMapId();
5719 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5723 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5725 unitTarget
->GetPosition(ox
,oy
,oz
);
5727 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5728 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5733 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5736 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5737 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, unitTarget
->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5739 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5743 void Spell::EffectReputation(uint32 i
)
5745 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5748 Player
*_player
= (Player
*)unitTarget
;
5750 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5752 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5754 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5759 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5762 void Spell::EffectQuestComplete(uint32 i
)
5764 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5767 Player
*_player
= (Player
*)m_caster
;
5769 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5770 _player
->AreaExploredOrEventHappens(quest_id
);
5773 void Spell::EffectSelfResurrect(uint32 i
)
5775 if(!unitTarget
|| unitTarget
->isAlive())
5777 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5779 if(!unitTarget
->IsInWorld())
5788 health
= uint32(-damage
);
5789 mana
= m_spellInfo
->EffectMiscValue
[i
];
5794 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5795 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5796 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5799 Player
*plr
= ((Player
*)unitTarget
);
5800 plr
->ResurrectPlayer(0.0f
);
5802 plr
->SetHealth( health
);
5803 plr
->SetPower(POWER_MANA
, mana
);
5804 plr
->SetPower(POWER_RAGE
, 0 );
5805 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5807 plr
->SpawnCorpseBones();
5812 void Spell::EffectSkinning(uint32
/*i*/)
5814 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5816 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5819 Creature
* creature
= (Creature
*) unitTarget
;
5820 int32 targetLevel
= creature
->getLevel();
5822 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5824 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5825 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5827 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5829 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5831 // Double chances for elites
5832 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5835 void Spell::EffectCharge(uint32
/*i*/)
5837 if(!unitTarget
|| !m_caster
)
5841 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5842 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5843 ((Creature
*)unitTarget
)->StopMoving();
5845 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5846 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5848 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5849 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5851 // not all charge effects used in negative spells
5852 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5853 m_caster
->Attack(unitTarget
,true);
5856 void Spell::EffectSummonCritter(uint32 i
)
5858 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5860 Player
* player
= (Player
*)m_caster
;
5862 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5866 Pet
* old_critter
= player
->GetMiniPet();
5868 // for same pet just despawn
5869 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5871 player
->RemoveMiniPet();
5875 // despawn old pet before summon new
5877 player
->RemoveMiniPet();
5880 Pet
* critter
= new Pet(MINI_PET
);
5882 Map
*map
= m_caster
->GetMap();
5883 uint32 pet_number
= objmgr
.GeneratePetNumber();
5884 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5885 pet_entry
, pet_number
))
5887 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5893 // If dest location if present
5894 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5896 x
= m_targets
.m_destX
;
5897 y
= m_targets
.m_destY
;
5898 z
= m_targets
.m_destZ
;
5900 // Summon if dest location not present near caster
5902 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5904 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5906 if(!critter
->IsPositionValid())
5908 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5909 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5914 critter
->SetOwnerGUID(m_caster
->GetGUID());
5915 critter
->SetCreatorGUID(m_caster
->GetGUID());
5916 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5917 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5919 critter
->AIM_Initialize();
5920 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5921 critter
->SetMaxHealth(1);
5922 critter
->SetHealth(1);
5923 critter
->SetLevel(1);
5925 // set timer for unsummon
5926 int32 duration
= GetSpellDuration(m_spellInfo
);
5928 critter
->SetDuration(duration
);
5930 std::string name
= player
->GetName();
5931 name
.append(petTypeSuffix
[critter
->getPetType()]);
5932 critter
->SetName( name
);
5933 player
->SetMiniPet(critter
);
5935 map
->Add((Creature
*)critter
);
5938 void Spell::EffectKnockBack(uint32 i
)
5940 if(!unitTarget
|| !m_caster
)
5943 // Effect only works on players
5944 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5947 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5948 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5950 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5951 data
.append(unitTarget
->GetPackGUID());
5952 data
<< uint32(0); // Sequence
5953 data
<< float(vcos
); // x direction
5954 data
<< float(vsin
); // y direction
5955 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5956 data
<< float(damage
/-10); // Z Movement speed (vertical)
5958 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5961 void Spell::EffectSendTaxi(uint32 i
)
5963 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5966 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5970 std::vector
<uint32
> nodes
;
5973 nodes
[0] = entry
->from
;
5974 nodes
[1] = entry
->to
;
5977 switch(m_spellInfo
->Id
)
5979 case 31606: //Stormcrow Amulet
5982 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5983 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5984 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5987 case 34905: //Stealth Flight
5990 case 45883: //Amber Ledge to Beryl Point
5993 case 46064: //Amber Ledge to Coldarra
5996 case 53335: //Stormwind Harbor Flight - Peaceful
6001 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
6005 void Spell::EffectPlayerPull(uint32 i
)
6007 if(!unitTarget
|| !m_caster
)
6010 // Effect only works on players
6011 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6014 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6015 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6017 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
6018 data
.append(unitTarget
->GetPackGUID());
6019 data
<< uint32(0); // Sequence
6020 data
<< float(vcos
); // x direction
6021 data
<< float(vsin
); // y direction
6023 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6024 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6026 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6029 void Spell::EffectDispelMechanic(uint32 i
)
6034 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6036 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6037 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6041 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6042 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6044 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6048 next
= Auras
.begin();
6054 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6056 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6058 Player
*_player
= (Player
*)m_caster
;
6059 Pet
*pet
= _player
->GetPet();
6066 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6067 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6068 pet
->setDeathState( ALIVE
);
6069 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6070 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6072 pet
->AIM_Initialize();
6074 _player
->PetSpellInitialize();
6075 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6078 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6081 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6083 if(!m_caster
->m_TotemSlot
[slot
])
6086 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6087 if(totem
&& totem
->isTotem())
6089 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6090 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6092 mana
+= spellInfo
->manaCost
* damage
/ 100;
6093 ((Totem
*)totem
)->UnSummon();
6097 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6098 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6101 void Spell::EffectDurabilityDamage(uint32 i
)
6103 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6106 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6108 // FIXME: some spells effects have value -1/-2
6109 // Possibly its mean -1 all player equipped items and -2 all items
6112 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6116 // invalid slot value
6117 if(slot
>= INVENTORY_SLOT_BAG_END
)
6120 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6121 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6124 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6126 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6129 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6131 // FIXME: some spells effects have value -1/-2
6132 // Possibly its mean -1 all player equipped items and -2 all items
6135 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6139 // invalid slot value
6140 if(slot
>= INVENTORY_SLOT_BAG_END
)
6146 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6147 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6150 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6155 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6158 void Spell::EffectTransmitted(uint32 effIndex
)
6160 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6162 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6166 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6172 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6174 fx
= m_targets
.m_destX
;
6175 fy
= m_targets
.m_destY
;
6176 fz
= m_targets
.m_destZ
;
6178 //FIXME: this can be better check for most objects but still hack
6179 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6181 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6182 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6186 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6187 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6188 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6190 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6193 Map
*cMap
= m_caster
->GetMap();
6195 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6197 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6198 { // but this is not proper, we really need to ignore not materialized objects
6199 SendCastResult(SPELL_FAILED_NOT_HERE
);
6200 SendChannelUpdate(0);
6204 // replace by water level in this case
6205 fz
= cMap
->GetWaterLevel(fx
,fy
);
6207 // if gameobject is summoning object, it should be spawned right on caster's position
6208 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6210 m_caster
->GetPosition(fx
,fy
,fz
);
6213 GameObject
* pGameObj
= new GameObject
;
6215 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6216 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6222 int32 duration
= GetSpellDuration(m_spellInfo
);
6224 switch(goinfo
->type
)
6226 case GAMEOBJECT_TYPE_FISHINGNODE
:
6228 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6230 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 2, 0.88431775569915771 );
6232 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 3, -0.4668855369091033 );
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
*1000 + FISHING_BOBBER_READY_TIME
*1000;
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
/1000 : 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\n");
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, 0, 0, 0, 100, 1))
6289 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 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 float px
= m_targets
.m_destX
;
6357 float py
= m_targets
.m_destY
;
6358 float pz
= m_targets
.m_destZ
;
6360 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6364 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6365 Charmed
->SetLevel(m_caster
->getLevel());
6367 // TODO: Add damage/mana/hp according to level
6369 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6371 // Enslave demon effect, without mana cost and cooldown
6372 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6375 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6379 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6380 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6381 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6382 This is why we use a half sec delay between the visual effect and the resurrection itself */
6383 void Spell::EffectSpiritHeal(uint32
/*i*/)
6386 if(!unitTarget || unitTarget->isAlive())
6388 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6390 if(!unitTarget->IsInWorld())
6393 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6394 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6395 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6396 ((Player*)unitTarget)->SpawnCorpseBones();
6400 // remove insignia spell effect
6401 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6403 sLog
.outDebug("Effect: SkinPlayerCorpse");
6404 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6407 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6410 void Spell::EffectStealBeneficialBuff(uint32 i
)
6412 sLog
.outDebug("Effect: StealBeneficialBuff");
6414 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6417 std::vector
<Aura
*> steal_list
;
6418 // Create dispel mask by dispel type
6419 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6420 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6421 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6423 Aura
*aur
= (*itr
).second
;
6424 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6426 // Need check for passive? this
6427 if (aur
->IsPositive() && !aur
->IsPassive())
6428 steal_list
.push_back(aur
);
6431 // Ok if exist some buffs for dispel try dispel it
6432 if (!steal_list
.empty())
6434 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6435 int32 list_size
= steal_list
.size();
6436 // Dispell N = damage buffs (or while exist buffs for dispel)
6437 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6439 // Random select buff for dispel
6440 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6441 // Not use chance for steal
6442 // TODO possible need do it
6443 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6445 // Remove buff from list for prevent doubles
6446 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6449 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6451 j
= steal_list
.erase(j
);
6458 // Really try steal and send log
6459 if (!success_list
.empty())
6461 int32 count
= success_list
.size();
6462 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6463 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6464 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6465 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6466 data
<< uint8(0); // not used
6467 data
<< uint32(count
); // count
6468 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6470 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6471 data
<< uint32(spellInfo
->Id
); // Spell Id
6472 data
<< uint8(0); // 0 - steals !=0 transfers
6473 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6475 m_caster
->SendMessageToSet(&data
, true);
6480 void Spell::EffectKillCredit(uint32 i
)
6482 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6485 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6488 void Spell::EffectQuestFail(uint32 i
)
6490 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6493 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6496 void Spell::EffectActivateRune(uint32 eff_idx
)
6498 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6501 Player
*plr
= (Player
*)m_caster
;
6503 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6506 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6508 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6510 plr
->SetRuneCooldown(j
, 0);
6515 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6517 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6518 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6521 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6523 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6524 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6527 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);