2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
24 #include "UpdateMask.h"
26 #include "ObjectMgr.h"
29 #include "SkillExtraItems.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
51 #include "SocialMgr.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
58 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
60 &Spell::EffectNULL
, // 0
61 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump
, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL
, //154 unused
215 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32
/*i*/)
224 sLog
.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32
/*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i
)
234 if(!unitTarget
|| unitTarget
->isAlive())
237 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
240 if(!unitTarget
->IsInWorld())
243 Player
* pTarget
= ((Player
*)unitTarget
);
245 if(pTarget
->isRessurectRequested()) // already have one active request
248 uint32 health
= damage
;
249 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
250 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
251 SendResurrectRequest(pTarget
);
254 void Spell::EffectInstaKill(uint32
/*i*/)
256 if( !unitTarget
|| !unitTarget
->isAlive() )
260 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
262 uint32 entry
= unitTarget
->GetEntry();
266 case 416: spellID
=18789; break; //imp
267 case 417: spellID
=18792; break; //fellhunter
268 case 1860: spellID
=18790; break; //void
269 case 1863: spellID
=18791; break; //succubus
270 case 17252: spellID
=35701; break; //fellguard
272 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry
);
276 m_caster
->CastSpell(m_caster
, spellID
, true);
279 if(m_caster
== unitTarget
) // prevent interrupt message
282 m_caster
->DealDamage(unitTarget
, unitTarget
->GetHealth(), NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
285 void Spell::EffectEnvirinmentalDMG(uint32 i
)
290 // Note: this hack with damage replace required until GO casting not implemented
291 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
292 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
293 damage
= m_spellInfo
->CalculateSimpleValue(i
);
295 m_caster
->CalcAbsorbResist(m_caster
, GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
297 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
298 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
299 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
, damage
);
302 void Spell::EffectSchoolDMG(uint32 effect_idx
)
304 if( unitTarget
&& unitTarget
->isAlive())
306 switch(m_spellInfo
->SpellFamilyName
)
308 case SPELLFAMILY_GENERIC
:
311 if(m_spellInfo
->SpellIconID
== 2269 )
313 damage
+= rand()%2 ? damage
: 0;
316 switch(m_spellInfo
->Id
) // better way to check unknown
318 // Meteor like spells (divided damage to targets)
319 case 24340: case 26558: case 28884: // Meteor
320 case 36837: case 38903: case 41276: // Meteor
321 case 26789: // Shard of the Fallen Star
322 case 31436: // Malevolent Cleave
323 case 35181: // Dive Bomb
324 case 40810: case 43267: case 43268: // Saber Lash
325 case 42384: // Brutal Swipe
326 case 45150: // Meteor Slash
329 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
330 if(ihit
->effectMask
& (1<<effect_idx
))
333 damage
/= count
; // divide to all targets
336 // percent from health with min
337 case 25599: // Thundercrash
339 damage
= unitTarget
->GetHealth() / 2;
344 // Intercept (warrior spell trigger)
348 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
353 damage
= unitTarget
->GetMaxHealth() / 2;
359 case SPELLFAMILY_MAGE
:
362 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
364 m_caster
->CastSpell(m_caster
, 36032, true);
368 case SPELLFAMILY_WARRIOR
:
371 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
373 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
376 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000020000000000LL
&& m_spellInfo
->Category
==1209)
377 damage
+= int32(m_caster
->GetShieldBlockValue());
379 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
381 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
382 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
384 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
385 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
386 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
387 // Heroic Throw ${$m1+$AP*.50}
388 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
389 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
390 // Shockwave ${$m3/100*$AP}
391 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
393 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
395 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
400 case SPELLFAMILY_WARLOCK
:
402 // Incinerate Rank 1 & 2
403 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
405 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
406 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
407 damage
+= int32(damage
*0.25f
);
411 case SPELLFAMILY_PRIEST
:
413 // Shadow Word: Death - deals damage equal to damage done to caster
414 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
415 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
418 case SPELLFAMILY_DRUID
:
421 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
423 // converts each extra point of energy into ($f1+$AP/410) additional damage
424 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
425 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
426 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
427 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
428 m_caster
->SetPower(POWER_ENERGY
,0);
431 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
433 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
436 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
438 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
440 //Mangle Bonus for the initial damage of Lacerate and Rake
441 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
442 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
444 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
445 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
446 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
448 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
454 case SPELLFAMILY_ROGUE
:
457 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
459 // consume from stack dozes not more that have combo-points
460 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
463 // Lookup for Deadly poison (only attacker applied)
464 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
465 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
466 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
467 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
468 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
473 // count consumed deadly poison doses at target
476 uint32 spellId
= poison
->GetId();
477 uint32 doses
= poison
->GetStackAmount();
480 for (int i
=0; i
< doses
; i
++)
481 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
483 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
485 // Eviscerate and Envenom Bonus Damage (item set effect)
486 if(m_caster
->GetDummyAura(37169))
487 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
491 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
493 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
495 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
496 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
498 // Eviscerate and Envenom Bonus Damage (item set effect)
499 if(m_caster
->GetDummyAura(37169))
504 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
506 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.21f
);
509 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
511 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
514 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
516 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
520 case SPELLFAMILY_HUNTER
:
523 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
525 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
528 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
530 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
533 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
535 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
538 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
540 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
541 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
543 // Explosive Trap Effect
544 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
546 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
550 case SPELLFAMILY_PALADIN
:
552 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
553 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
555 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
556 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
557 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
558 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
559 // Get stack of Holy Vengeance on the target added by caster
561 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
562 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
563 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
565 stacks
= (*itr
)->GetStackAmount();
568 // + 10% for each application of Holy Vengeance on the target
570 damage
+= damage
* stacks
* 10 /100;
572 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
573 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
575 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
576 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
577 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
578 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
580 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
581 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
583 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
584 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
585 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
586 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
588 // Hammer of the Righteous
589 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
591 // Add main hand dps * effect[2] amount
592 float average
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
593 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
594 damage
+= count
* int32(average
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
596 // Shield of Righteousness
597 else if(m_spellInfo
->SpellFamilyFlags
&0x0010000000000000LL
)
599 damage
+=int32(m_caster
->GetShieldBlockValue());
610 void Spell::EffectDummy(uint32 i
)
612 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
615 // selection by spell family
616 switch(m_spellInfo
->SpellFamilyName
)
618 case SPELLFAMILY_GENERIC
:
620 switch(m_spellInfo
->Id
)
622 case 8063: // Deviate Fish
624 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
630 case 1: spell_id
= 8064; break; // Sleepy
631 case 2: spell_id
= 8065; break; // Invigorate
632 case 3: spell_id
= 8066; break; // Shrink
633 case 4: spell_id
= 8067; break; // Party Time!
634 case 5: spell_id
= 8068; break; // Healthy Spirit
636 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
639 case 8213: // Savory Deviate Delight
641 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
648 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
650 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
652 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
655 case 8593: // Symbol of life (restore creature to life)
656 case 31225: // Shimmering Vessel (restore creature to life)
658 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
660 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
663 case 12162: // Deep wounds
664 case 12850: // (now good common check for this spells)
671 // DW should benefit of attack power, damage percent mods etc.
672 // TODO: check if using offhand damage is correct and if it should be divided by 2
673 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
674 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
676 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
678 switch (m_spellInfo
->Id
)
680 case 12850: damage
*= 0.2f
; break;
681 case 12162: damage
*= 0.4f
; break;
682 case 12868: damage
*= 0.6f
; break;
684 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
688 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
689 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
692 case 13120: // net-o-matic
699 uint32 roll
= urand(0, 99);
701 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
703 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
708 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
711 case 13567: // Dummy Trigger
713 // can be used for different aura triggering, so select by aura
714 if(!m_triggeredByAuraSpell
|| !unitTarget
)
717 switch(m_triggeredByAuraSpell
->Id
)
719 case 26467: // Persistent Shield
720 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
723 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
728 case 15998: // Capture Worg Pup
729 case 29435: // Capture Female Kaliri Hatchling
731 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
734 Creature
* creatureTarget
= (Creature
*)unitTarget
;
735 creatureTarget
->setDeathState(JUST_DIED
);
736 creatureTarget
->RemoveCorpse();
737 creatureTarget
->SetHealth(0); // just for nice GM-mode view
740 case 16589: // Noggenfogger Elixir
742 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
748 case 1: spell_id
= 16595; break;
749 case 2: spell_id
= 16593; break;
750 default:spell_id
= 16591; break;
753 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
756 case 17251: // Spirit Healer Res
758 if(!unitTarget
|| !m_originalCaster
)
761 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
763 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
764 data
<< uint64(unitTarget
->GetGUID());
765 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
769 case 17271: // Test Fetid Skull
771 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
774 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
776 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
779 case 20577: // Cannibalize
781 m_caster
->CastSpell(m_caster
, 20578, false, NULL
);
783 case 23019: // Crystal Prison Dummy DND
785 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
788 Creature
* creatureTarget
= (Creature
*)unitTarget
;
789 if(creatureTarget
->isPet())
792 GameObject
* pGameObj
= new GameObject
;
794 Map
*map
= creatureTarget
->GetMap();
796 // create before death for get proper coordinates
797 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
798 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
799 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
) )
805 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
806 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
807 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
808 pGameObj
->SetSpellId(m_spellInfo
->Id
);
810 creatureTarget
->setDeathState(JUST_DIED
);
811 creatureTarget
->RemoveCorpse();
812 creatureTarget
->SetHealth(0); // just for nice GM-mode view
814 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
817 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
818 data
<< uint64(pGameObj
->GetGUID());
819 m_caster
->SendMessageToSet(&data
, true);
823 case 23074: // Arcanite Dragonling
824 if (!m_CastItem
) return;
825 m_caster
->CastSpell(m_caster
, 19804, true, m_CastItem
);
827 case 23075: // Mithril Mechanical Dragonling
828 if (!m_CastItem
) return;
829 m_caster
->CastSpell(m_caster
, 12749, true, m_CastItem
);
831 case 23076: // Mechanical Dragonling
832 if (!m_CastItem
) return;
833 m_caster
->CastSpell(m_caster
, 4073, true, m_CastItem
);
835 case 23133: // Gnomish Battle Chicken
836 if (!m_CastItem
) return;
837 m_caster
->CastSpell(m_caster
, 13166, true, m_CastItem
);
839 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
841 int32 r
= irand(0, 119);
842 if ( r
< 20 ) // 1/6 polymorph
843 m_caster
->CastSpell(m_caster
, 23444, true);
844 else if ( r
< 100 ) // 4/6 evil twin
845 m_caster
->CastSpell(m_caster
, 23445, true);
846 else // 1/6 miss the target
847 m_caster
->CastSpell(m_caster
, 36902, true);
850 case 23453: // Ultrasafe Transporter: Gadgetzan
851 if ( roll_chance_i(50) ) // success
852 m_caster
->CastSpell(m_caster
, 23441, true);
854 m_caster
->CastSpell(m_caster
, 23446, true);
856 case 23645: // Hourglass Sand
857 m_caster
->RemoveAurasDueToSpell(23170);
859 case 23725: // Gift of Life (warrior bwl trinket)
860 m_caster
->CastSpell(m_caster
, 23782, true);
861 m_caster
->CastSpell(m_caster
, 23783, true);
863 case 25860: // Reindeer Transformation
865 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
868 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
869 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
871 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
873 //5 different spells used depending on mounted speed and if mount can fly or not
874 if (flyspeed
>= 4.1f
)
875 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
876 else if (flyspeed
>= 3.8f
)
877 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
878 else if (flyspeed
>= 1.6f
)
879 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
880 else if (speed
>= 2.0f
)
881 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
883 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
887 //case 26074: // Holiday Cheer
888 // return; -- implemented at client side
889 case 28006: // Arcane Cloaking
891 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
892 m_caster
->CastSpell(unitTarget
, 29294, true);
895 case 28730: // Arcane Torrent (Mana)
897 Aura
* dummy
= m_caster
->GetDummyAura(28734);
900 int32 bp
= damage
* dummy
->GetStackAmount();
901 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
902 m_caster
->RemoveAurasDueToSpell(28734);
906 case 29200: // Purify Helboar Meat
908 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
911 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
913 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
916 case 29858: // Soulshatter
917 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
918 m_caster
->CastSpell(unitTarget
,32835,true);
920 case 30458: // Nigh Invulnerability
921 if (!m_CastItem
) return;
922 if(roll_chance_i(86)) // success
923 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
924 else // backfire in 14% casts
925 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
927 case 30507: // Poultryizer
928 if (!m_CastItem
) return;
929 if(roll_chance_i(80)) // success
930 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
932 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
934 case 33060: // Make a Wish
936 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
943 case 1: spell_id
= 33053; break;
944 case 2: spell_id
= 33057; break;
945 case 3: spell_id
= 33059; break;
946 case 4: spell_id
= 33062; break;
947 case 5: spell_id
= 33064; break;
950 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
956 switch(m_caster
->GetAreaId())
958 case 3900: spell_id
= 35743; break;
959 case 3742: spell_id
= 35744; break;
963 m_caster
->CastSpell(m_caster
, spell_id
, true);
966 case 37674: // Chaos Blast
971 int32 basepoints0
= 100;
972 m_caster
->CastCustomSpell(unitTarget
, 37675, &basepoints0
, NULL
, NULL
, true);
975 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
977 // selecting one from Bloodstained Fortune item
981 case 1: newitemid
= 32688; break;
982 case 2: newitemid
= 32689; break;
983 case 3: newitemid
= 32690; break;
984 case 4: newitemid
= 32691; break;
985 case 5: newitemid
= 32692; break;
986 case 6: newitemid
= 32693; break;
987 case 7: newitemid
= 32700; break;
988 case 8: newitemid
= 32701; break;
989 case 9: newitemid
= 32702; break;
990 case 10: newitemid
= 32703; break;
991 case 11: newitemid
= 32704; break;
992 case 12: newitemid
= 32705; break;
993 case 13: newitemid
= 32706; break;
994 case 14: newitemid
= 32707; break;
995 case 15: newitemid
= 32708; break;
996 case 16: newitemid
= 32709; break;
997 case 17: newitemid
= 32710; break;
998 case 18: newitemid
= 32711; break;
999 case 19: newitemid
= 32712; break;
1000 case 20: newitemid
= 32713; break;
1005 DoCreateItem(i
, newitemid
);
1008 // Demon Broiled Surprise
1009 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1012 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1015 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1019 case 44875: // Complete Raptor Capture
1021 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1024 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1026 creatureTarget
->setDeathState(JUST_DIED
);
1027 creatureTarget
->RemoveCorpse();
1028 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1030 //cast spell Raptor Capture Credit
1031 m_caster
->CastSpell(m_caster
, 42337, true, NULL
);
1034 case 34665: //Administer Antidote
1036 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1042 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1046 uint32 health
= tempSummon
->GetHealth();
1048 float x
= tempSummon
->GetPositionX();
1049 float y
= tempSummon
->GetPositionY();
1050 float z
= tempSummon
->GetPositionZ();
1051 float o
= tempSummon
->GetOrientation();
1052 tempSummon
->UnSummon();
1054 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1058 pCreature
->SetHealth(health
);
1059 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992, pCreature
);
1061 if (pCreature
->AI())
1062 pCreature
->AI()->AttackStart(m_caster
);
1066 case 44997: // Converting Sentry
1068 //Converted Sentry Credit
1069 m_caster
->CastSpell(m_caster
, 45009, true);
1072 case 45030: // Impale Emissary
1074 // Emissary of Hate Credit
1075 m_caster
->CastSpell(m_caster
, 45088, true);
1078 case 50243: // Teach Language
1080 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1083 // spell has a 1/3 chance to trigger one of the below
1084 if(roll_chance_i(66))
1086 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1088 // 1000001 - gnomish binary
1089 m_caster
->CastSpell(m_caster
, 50242, true);
1093 // 01001000 - goblin binary
1094 m_caster
->CastSpell(m_caster
, 50246, true);
1099 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1101 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1104 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1105 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1107 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1110 case 51592: // Pickup Primordial Hatchling
1112 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1115 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1117 creatureTarget
->setDeathState(JUST_DIED
);
1118 creatureTarget
->RemoveCorpse();
1119 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1129 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1130 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1132 if (m_caster
->HasAura(reqAuraID
,0))
1133 m_caster
->CastSpell(m_caster
, spellID
, true, NULL
);
1137 return; // additional data for dummy[0]
1141 case 52759: // Ancestral Awakening
1144 m_caster
->CastCustomSpell(unitTarget
, 52752, &damage
, NULL
, NULL
, true);
1149 m_caster
->CastSpell(m_caster
, 54586, true);
1152 case 58418: // Portal to Orgrimmar
1153 case 58420: // Portal to Stormwind
1154 return; // implemented in EffectScript[0]
1157 //All IconID Check in there
1158 switch(m_spellInfo
->SpellIconID
)
1160 // Berserking (troll racial traits)
1163 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1164 int32 melee_mod
= 10;
1165 if (healthPerc
<= 40)
1167 if (healthPerc
< 100 && healthPerc
> 40)
1168 melee_mod
= 10+(100-healthPerc
)/3;
1170 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1171 int32 hasteModBasePoints1
= (5-melee_mod
);
1172 int32 hasteModBasePoints2
= 5;
1174 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1175 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1176 m_caster
->CastCustomSpell(m_caster
, 26635, &hasteModBasePoints0
, &hasteModBasePoints1
, &hasteModBasePoints2
, true, NULL
);
1182 case SPELLFAMILY_MAGE
:
1183 switch(m_spellInfo
->Id
)
1185 case 11958: // Cold Snap
1187 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1190 // immediately finishes the cooldown on Frost spells
1191 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1192 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1194 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1197 uint32 classspell
= itr
->first
;
1198 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1200 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1201 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1202 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1204 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
, true);
1211 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1213 //Polymorph Cast Visual Rank 1
1214 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1215 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1221 case SPELLFAMILY_WARRIOR
:
1223 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1225 int32 chargeBasePoints0
= damage
;
1226 m_caster
->CastCustomSpell(m_caster
, 34846, &chargeBasePoints0
, NULL
, NULL
, true);
1230 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1235 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1236 // Glyph of Execution bonus
1237 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1238 rage
+=aura
->GetModifier()->m_amount
;
1240 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1241 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1242 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1243 m_caster
->SetPower(POWER_RAGE
, 0);
1247 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1251 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1256 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000004000000LL
)
1258 m_damage
+= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
1261 switch(m_spellInfo
->Id
)
1268 m_caster
->CastSpell(unitTarget
, 21887, true);// spell mod
1274 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1275 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1281 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1286 case SPELLFAMILY_WARLOCK
:
1288 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1290 // In 303 exist spirit depend
1291 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1292 switch (m_spellInfo
->Id
)
1294 case 1454: damage
+=spirit
; break;
1295 case 1455: damage
+=spirit
*15/10; break;
1296 case 1456: damage
+=spirit
*2; break;
1297 case 11687: damage
+=spirit
*25/10; break;
1301 case 57946: damage
+=spirit
*3; break;
1303 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1306 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1307 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1308 if(unitTarget
&& (int32(unitTarget
->GetHealth()) > damage
))
1310 // Shouldn't Appear in Combat Log
1311 unitTarget
->ModifyHealth(-damage
);
1313 int32 mana
= damage
;
1314 // Improved Life Tap mod
1315 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1316 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1318 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1319 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1321 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1324 int32 manaFeedVal
= 0;
1325 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1326 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1328 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1329 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1333 manaFeedVal
= manaFeedVal
* mana
/ 100;
1334 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1338 SendCastResult(SPELL_FAILED_FIZZLE
);
1342 case SPELLFAMILY_PRIEST
:
1344 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1351 switch(m_spellInfo
->Id
)
1353 case 47540: hurt
= 47758; heal
= 47757; break;
1354 case 53005: hurt
= 53001; heal
= 52986; break;
1355 case 53006: hurt
= 53002; heal
= 52987; break;
1356 case 53007: hurt
= 53003; heal
= 52988; break;
1358 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1361 if (m_caster
->IsFriendlyTo(unitTarget
))
1362 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1364 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1368 case SPELLFAMILY_DRUID
:
1370 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000100LL
)
1372 //Shapeshifting into an animal form or mounting cancels the effect.
1373 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1375 if(m_triggeredByAuraSpell
)
1376 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1380 //Any effect which causes you to lose control of your character will supress the starfall effect.
1381 if(m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1384 switch(m_spellInfo
->Id
)
1386 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1387 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1388 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1389 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1391 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1396 case SPELLFAMILY_ROGUE
:
1397 switch(m_spellInfo
->Id
)
1401 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1404 Player
*pCaster
= ((Player
*)m_caster
);
1406 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1410 // all poison enchantments is temporary
1411 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1415 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1419 for (int s
=0;s
<3;s
++)
1421 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1424 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1425 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1428 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1431 m_caster
->CastSpell(unitTarget
, 5940, true);
1434 case 14185: // Preparation Rogue
1436 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1439 //immediately finishes the cooldown on certain Rogue abilities
1440 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1441 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1443 uint32 classspell
= itr
->first
;
1444 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1446 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1447 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
,true);
1451 case 31231: // Cheat Death
1453 m_caster
->CastSpell(m_caster
, 45182, true);
1458 case SPELLFAMILY_HUNTER
:
1460 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1462 if( !unitTarget
|| !unitTarget
->isAlive())
1467 // check dazed affect
1468 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1469 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1471 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1483 switch(m_spellInfo
->Id
)
1485 case 23989: //Readiness talent
1487 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1490 //immediately finishes the cooldown for hunter abilities
1491 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1492 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1494 uint32 classspell
= itr
->first
;
1495 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1497 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1498 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
,true);
1502 case 37506: // Scatter Shot
1504 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1507 // break Auto Shot and autohit
1508 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1509 m_caster
->AttackStop();
1510 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1515 case SPELLFAMILY_PALADIN
:
1516 switch(m_spellInfo
->SpellIconID
)
1518 case 156: // Holy Shock
1526 switch(m_spellInfo
->Id
)
1528 case 20473: hurt
= 25912; heal
= 25914; break;
1529 case 20929: hurt
= 25911; heal
= 25913; break;
1530 case 20930: hurt
= 25902; heal
= 25903; break;
1531 case 27174: hurt
= 27176; heal
= 27175; break;
1532 case 33072: hurt
= 33073; heal
= 33074; break;
1533 case 48824: hurt
= 48822; heal
= 48820; break;
1534 case 48825: hurt
= 48823; heal
= 48821; break;
1536 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1540 if(m_caster
->IsFriendlyTo(unitTarget
))
1541 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1543 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1547 case 561: // Judgement of command
1552 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1553 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1557 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1559 // decreased damage (/2) for non-stunned target.
1560 SpellModifier
*mod
= new SpellModifier
;
1561 mod
->op
= SPELLMOD_DAMAGE
;
1563 mod
->type
= SPELLMOD_PCT
;
1564 mod
->spellId
= m_spellInfo
->Id
;
1565 mod
->mask
= 0x0000020000000000LL
;
1568 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1569 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
1571 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1574 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
1580 switch(m_spellInfo
->Id
)
1582 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1587 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1590 case 31789: // Righteous Defense (step 1)
1592 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1594 // non-standard cast requirement check
1595 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1597 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1598 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
,true);
1599 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1603 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1604 // Clear targets for eff 1
1605 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1606 ihit
->effectMask
&= ~(1<<1);
1608 // not empty (checked)
1609 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1611 // chance to be selected from list
1612 float chance
= 100.0f
/attackers
.size();
1614 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1616 if(!roll_chance_f(chance
))
1619 AddUnitTarget((*aItr
), 1);
1622 // now let next effect cast spell at each target.
1625 case 37877: // Blessing of Faith
1630 uint32 spell_id
= 0;
1631 switch(unitTarget
->getClass())
1633 case CLASS_DRUID
: spell_id
= 37878; break;
1634 case CLASS_PALADIN
: spell_id
= 37879; break;
1635 case CLASS_PRIEST
: spell_id
= 37880; break;
1636 case CLASS_SHAMAN
: spell_id
= 37881; break;
1637 default: return; // ignore for not healing classes
1640 m_caster
->CastSpell(m_caster
, spell_id
, true);
1645 case SPELLFAMILY_SHAMAN
:
1646 //Shaman Rockbiter Weapon
1647 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1649 // TODO: use expect spell for enchant (if exist talent)
1650 // In 3.0.3 no mods present for rockbiter
1651 uint32 spell_id
= 0;
1652 switch(m_spellInfo
->Id
)
1654 case 8017: spell_id
= 36494; break; // Rank 1
1655 case 8018: spell_id
= 36750; break; // Rank 2
1656 case 8019: spell_id
= 36755; break; // Rank 3
1657 case 10399: spell_id
= 36759; break; // Rank 4
1659 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo
->Id
);
1663 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1667 sLog
.outError("WORLD: unknown spell id %i", spell_id
);
1671 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1674 for(int j
= BASE_ATTACK
; j
<= OFF_ATTACK
; ++j
)
1676 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(j
)))
1678 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1680 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1682 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1683 // at calculation applied affect from Elemental Weapons talent
1684 // real enchantment damage-1
1685 spell
->m_currentBasePoints
[1] = damage
-1;
1687 SpellCastTargets targets
;
1688 targets
.setItemTarget( item
);
1689 spell
->prepare(&targets
);
1696 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000004000000LL
&& m_spellInfo
->SpellIconID
==1673)
1698 m_caster
->CastSpell(unitTarget
, 52025, true);
1701 // Healing Stream Totem
1702 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1704 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1707 // Mana Spring Totem
1708 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1710 if(unitTarget
->getPowerType()!=POWER_MANA
)
1712 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1715 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1717 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1719 // Glyph of Mana Tide
1720 Unit
*owner
= m_caster
->GetOwner();
1722 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1723 damage
+=dummy
->GetModifier()->m_amount
;
1724 // Regenerate 6% of Total Mana Every 3 secs
1725 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1726 m_caster
->CastCustomSpell(unitTarget
, 39609, &EffectBasePoints0
, NULL
, NULL
, true, NULL
, NULL
, m_originalCasterGUID
);
1730 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1732 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1734 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1737 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1738 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1739 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1741 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1742 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1743 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1745 m_damage
+= m_damage
* damage
/ 100;
1753 case SPELLFAMILY_DEATHKNIGHT
:
1755 if(m_spellInfo
->SpellFamilyFlags
& 0x002000LL
)
1757 if(m_caster
->IsFriendlyTo(unitTarget
))
1759 if(unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1762 int32 bp
= damage
* 1.5f
;
1763 m_caster
->CastCustomSpell(unitTarget
, 47633, &bp
, NULL
, NULL
, true);
1768 m_caster
->CastCustomSpell(unitTarget
, 47632, &bp
, NULL
, NULL
, true);
1776 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1778 m_caster
->AddPetAura(petSpell
);
1782 // Script based implementation. Must be used only for not good for implementation in core spell effects
1783 // So called only for not proccessed cases
1785 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
1786 else if(unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
1787 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
1789 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
1792 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1794 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1797 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1801 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1806 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1809 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1811 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1812 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1816 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1821 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1823 SpellCastTargets targets
;
1824 targets
.setUnitTarget( unitTarget
);
1825 spell
->prepare(&targets
);
1827 m_caster
->SetCurrentCastedSpell(spell
);
1828 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1832 void Spell::EffectForceCast(uint32 i
)
1837 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1840 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1844 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1848 unitTarget
->CastSpell(unitTarget
, spellInfo
, true, NULL
, NULL
, m_originalCasterGUID
);
1851 void Spell::EffectTriggerSpell(uint32 i
)
1853 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1856 switch(triggered_spell_id
)
1861 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1862 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1863 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1865 // if this spell is given to NPC it must handle rest by it's own AI
1866 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1869 // get highest rank of the Stealth spell
1871 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1872 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1874 // only highest rank is shown in spell book, so simply check if shown in spell book
1875 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1878 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1882 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1884 spellId
= spellInfo
->Id
;
1889 // no Stealth spell found
1893 // reset cooldown on it if needed
1894 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1895 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1897 m_caster
->CastSpell(m_caster
, spellId
, true);
1901 case 23770: // Sayge's Dark Fortune of *
1902 // not exist, common cooldown can be implemented in scripts if need.
1904 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1907 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1911 for (int j
=0; j
< spell
->StackAmount
; ++j
)
1912 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1915 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1918 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1922 for (int j
=0; j
< spell
->StackAmount
; ++j
)
1923 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1926 // Righteous Defense
1929 m_caster
->CastSpell(unitTarget
, 31790, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1935 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1936 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1938 // remove all harmful spells on you...
1939 if( // ignore positive and passive auras
1940 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1941 // ignore physical auras
1942 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1944 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1945 iter
= Auras
.begin();
1950 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1953 if (Unit
*pet
= m_caster
->GetPet())
1954 pet
->CastSpell(pet
, 28305, true);
1960 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1964 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1968 // some triggered spells require specific equipment
1969 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1971 // main hand weapon required
1972 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1974 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1976 // skip spell if no weapon in slot or broken
1977 if(!item
|| item
->IsBroken() )
1980 // skip spell if weapon not fit to triggered spell
1981 if(!item
->IsFitToSpellRequirements(spellInfo
))
1985 // offhand hand weapon required
1986 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1988 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1990 // skip spell if no weapon in slot or broken
1991 if(!item
|| item
->IsBroken() )
1994 // skip spell if weapon not fit to triggered spell
1995 if(!item
->IsFitToSpellRequirements(spellInfo
))
2000 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
2001 bool instant
= false;
2002 for(uint32 j
= i
+1; j
< 3; ++j
)
2004 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
2014 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
2017 m_TriggerSpells
.push_back(spellInfo
);
2020 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2022 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2025 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2029 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2030 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2035 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2037 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2040 void Spell::EffectJump(uint32 i
)
2042 if(m_caster
->isInFlight())
2045 // Init dest coordinates
2047 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2049 x
= m_targets
.m_destX
;
2050 y
= m_targets
.m_destY
;
2051 z
= m_targets
.m_destZ
;
2053 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2055 // explicit cast data from client or server-side cast
2056 // some spell at client send caster
2057 Unit
* pTarget
= NULL
;
2058 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2059 pTarget
= m_targets
.getUnitTarget();
2060 else if(unitTarget
->getVictim())
2061 pTarget
= m_caster
->getVictim();
2062 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2063 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2065 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2068 o
= m_caster
->GetOrientation();
2072 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2073 o
= m_caster
->GetOrientation();
2075 else if(gameObjTarget
)
2077 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2078 o
= m_caster
->GetOrientation();
2082 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2086 m_caster
->NearTeleportTo(x
, y
, z
, o
, true);
2089 void Spell::EffectTeleportUnits(uint32 i
)
2091 if(!unitTarget
|| unitTarget
->isInFlight())
2094 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2096 case TARGET_INNKEEPER_COORDINATES
:
2098 // Only players can teleport to innkeeper
2099 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2102 ((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);
2105 case TARGET_AREAEFFECT_INSTANT
: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2106 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2108 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2111 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2115 if(st
->target_mapId
==unitTarget
->GetMapId())
2116 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2117 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2118 ((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);
2121 case TARGET_BEHIND_VICTIM
:
2123 Unit
*pTarget
= NULL
;
2125 // explicit cast data from client or server-side cast
2126 // some spell at client send caster
2127 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2128 pTarget
= m_targets
.getUnitTarget();
2129 else if(unitTarget
->getVictim())
2130 pTarget
= unitTarget
->getVictim();
2131 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2132 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2134 // Init dest coordinates
2135 float x
= m_targets
.m_destX
;
2136 float y
= m_targets
.m_destY
;
2137 float z
= m_targets
.m_destZ
;
2138 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2139 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2144 // If not exist data for dest location - return
2145 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2147 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2150 // Init dest coordinates
2151 float x
= m_targets
.m_destX
;
2152 float y
= m_targets
.m_destY
;
2153 float z
= m_targets
.m_destZ
;
2154 float orientation
= unitTarget
->GetOrientation();
2156 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2161 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2162 switch ( m_spellInfo
->Id
)
2164 // Dimensional Ripper - Everlook
2167 int32 r
= irand(0, 119);
2168 if ( r
>= 70 ) // 7/12 success
2170 if ( r
< 100 ) // 4/12 evil twin
2171 m_caster
->CastSpell(m_caster
, 23445, true);
2173 m_caster
->CastSpell(m_caster
, 23449, true);
2177 // Ultrasafe Transporter: Toshley's Station
2180 if ( roll_chance_i(50) ) // 50% success
2182 int32 rand_eff
= urand(1, 7);
2186 // soul split - evil
2187 m_caster
->CastSpell(m_caster
, 36900, true);
2190 // soul split - good
2191 m_caster
->CastSpell(m_caster
, 36901, true);
2194 // Increase the size
2195 m_caster
->CastSpell(m_caster
, 36895, true);
2198 // Decrease the size
2199 m_caster
->CastSpell(m_caster
, 36893, true);
2204 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2205 m_caster
->CastSpell(m_caster
, 36897, true);
2207 m_caster
->CastSpell(m_caster
, 36899, true);
2212 m_caster
->CastSpell(m_caster
, 36940, true);
2216 m_caster
->CastSpell(m_caster
, 23445, true);
2222 // Dimensional Ripper - Area 52
2225 if ( roll_chance_i(50) ) // 50% success
2227 int32 rand_eff
= urand(1, 4);
2231 // soul split - evil
2232 m_caster
->CastSpell(m_caster
, 36900, true);
2235 // soul split - good
2236 m_caster
->CastSpell(m_caster
, 36901, true);
2239 // Increase the size
2240 m_caster
->CastSpell(m_caster
, 36895, true);
2245 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2246 m_caster
->CastSpell(m_caster
, 36897, true);
2248 m_caster
->CastSpell(m_caster
, 36899, true);
2258 void Spell::EffectApplyAura(uint32 i
)
2263 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2264 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2265 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2268 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2272 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2274 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2276 // Now Reduce spell duration using data received at spell hit
2277 int32 duration
= Aur
->GetAuraMaxDuration();
2278 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
, duration
, m_caster
, m_diminishLevel
);
2279 Aur
->setDiminishGroup(m_diminishGroup
);
2281 // if Aura removed and deleted, do not continue.
2282 if(duration
== 0 && !(Aur
->IsPermanent()))
2288 if(duration
!= Aur
->GetAuraMaxDuration())
2290 Aur
->SetAuraMaxDuration(duration
);
2291 Aur
->SetAuraDuration(duration
);
2294 bool added
= unitTarget
->AddAura(Aur
);
2296 // Aura not added and deleted in AddAura call;
2300 // found crash at character loading, broken pointer to Aur...
2301 // Aur was deleted in AddAura()...
2305 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2306 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2307 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2310 void Spell::EffectUnlearnSpecialization( uint32 i
)
2312 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2315 Player
*_player
= (Player
*)unitTarget
;
2316 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2318 _player
->removeSpell(spellToUnlearn
);
2320 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2323 void Spell::EffectPowerDrain(uint32 i
)
2325 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2328 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2332 if(!unitTarget
->isAlive())
2334 if(unitTarget
->getPowerType() != drain_power
)
2339 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2341 //add spell damage bonus
2342 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2344 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2345 uint32 power
= damage
;
2346 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2347 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2350 if(curPower
< power
)
2351 new_damage
= curPower
;
2355 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2357 // Don`t restore from self drain
2358 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2360 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2361 if(manaMultiplier
==0)
2364 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2365 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2367 int32 gain
= int32(new_damage
* manaMultiplier
);
2369 m_caster
->ModifyPower(POWER_MANA
,gain
);
2371 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
2375 void Spell::EffectSendEvent(uint32 EffectIndex
)
2378 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2380 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2381 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2384 void Spell::EffectPowerBurn(uint32 i
)
2386 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2389 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2393 if(!unitTarget
->isAlive())
2395 if(unitTarget
->getPowerType()!=powertype
)
2400 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2401 if(m_spellInfo
->ManaCostPercentage
)
2403 uint32 maxdamage
= m_caster
->GetMaxPower(powertype
) * damage
* 2 / 100;
2404 damage
= unitTarget
->GetMaxPower(powertype
) * damage
/ 100;
2405 if(damage
> maxdamage
) damage
= maxdamage
;
2408 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2410 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2411 uint32 power
= damage
;
2412 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2413 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2415 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2417 unitTarget
->ModifyPower(powertype
, -new_damage
);
2418 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2420 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2421 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2423 new_damage
= int32(new_damage
* multiplier
);
2424 m_damage
+= new_damage
;
2427 void Spell::EffectHeal( uint32
/*i*/ )
2429 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2431 // Try to get original caster
2432 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2434 // Skip if m_originalCaster not available
2438 int32 addhealth
= damage
;
2440 // Vessel of the Naaru (Vial of the Sunwell trinket)
2441 if (m_spellInfo
->Id
== 45064)
2443 // Amount of heal - depends from stacked Holy Energy
2444 int damageAmount
= 0;
2445 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2446 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
2447 if((*i
)->GetId() == 45062)
2448 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2450 m_caster
->RemoveAurasDueToSpell(45062);
2452 addhealth
+= damageAmount
;
2454 // Swiftmend - consumes Regrowth or Rejuvenation
2455 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2457 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2458 // find most short by duration
2459 Aura
*targetAura
= NULL
;
2460 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2462 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2463 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2465 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2472 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2478 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2483 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2484 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2485 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2487 addhealth
+= tickheal
* tickcount
;
2490 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2492 m_healing
+=addhealth
;
2496 void Spell::EffectHealPct( uint32
/*i*/ )
2498 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2500 // Try to get original caster
2501 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2503 // Skip if m_originalCaster not available
2507 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2508 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2509 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DAMAGE
, addhealth
, this);
2511 int32 gain
= caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2512 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2516 void Spell::EffectHealMechanical( uint32
/*i*/ )
2518 // Mechanic creature type should be correctly checked by targetCreatureType field
2519 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2521 // Try to get original caster
2522 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2524 // Skip if m_originalCaster not available
2528 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2529 caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2533 void Spell::EffectHealthLeech(uint32 i
)
2537 if(!unitTarget
->isAlive())
2543 sLog
.outDebug("HealthLeech :%i", damage
);
2545 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2547 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2548 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2550 int32 new_damage
= int32(damage
*multiplier
);
2551 uint32 curHealth
= unitTarget
->GetHealth();
2552 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
);
2553 if(curHealth
< new_damage
)
2554 new_damage
= curHealth
;
2556 if(m_caster
->isAlive())
2558 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2559 m_caster
->DealHeal(m_caster
, uint32(new_damage
), m_spellInfo
);
2561 // m_healthLeech+=tmpvalue;
2562 // m_damage+=new_damage;
2565 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2567 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2570 Player
* player
= (Player
*)unitTarget
;
2572 uint32 newitemid
= itemtype
;
2573 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2576 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2582 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2583 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2585 int32 basePoints
= m_currentBasePoints
[i
];
2586 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2588 num_to_add
= basePoints
+ irand(1, randomPoints
);
2590 num_to_add
= basePoints
+ 1;
2592 else if (pProto
->MaxCount
== 1)
2594 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2596 int32 basePoints
= m_currentBasePoints
[i
];
2597 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2598 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2605 if (num_to_add
> pProto
->GetMaxStackSize())
2606 num_to_add
= pProto
->GetMaxStackSize();
2608 // init items_count to 1, since 1 item will be created regardless of specialization
2610 // the chance to create additional items
2611 float additionalCreateChance
=0.0f
;
2612 // the maximum number of created additional items
2613 uint8 additionalMaxNum
=0;
2614 // get the chance and maximum number for creating extra items
2615 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2617 // roll with this chance till we roll not to create or we create the max num
2618 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2622 // really will be created more items
2623 num_to_add
*= items_count
;
2625 // can the player store the new item?
2626 ItemPosCountVec dest
;
2627 uint32 no_space
= 0;
2628 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2629 if( msg
!= EQUIP_ERR_OK
)
2631 // convert to possible store amount
2632 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2633 num_to_add
-= no_space
;
2636 // if not created by another reason from full inventory or unique items amount limitation
2637 player
->SendEquipError( msg
, NULL
, NULL
);
2644 // create the new item and store it
2645 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2647 // was it successful? return error if not
2650 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2654 // set the "Crafted by ..." property of the item
2655 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2656 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
, player
->GetGUIDLow());
2658 // send info to the client
2660 player
->SendNewItem(pItem
, num_to_add
, true, true);
2662 // we succeeded in creating at least one item, so a levelup is possible
2663 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2666 // for battleground marks send by mail if not add all expected
2669 BattleGroundTypeId bgType
;
2670 switch(m_spellInfo
->Id
)
2672 case SPELL_AV_MARK_WINNER
:
2673 case SPELL_AV_MARK_LOSER
:
2674 bgType
= BATTLEGROUND_AV
;
2676 case SPELL_WS_MARK_WINNER
:
2677 case SPELL_WS_MARK_LOSER
:
2678 bgType
= BATTLEGROUND_WS
;
2680 case SPELL_AB_MARK_WINNER
:
2681 case SPELL_AB_MARK_LOSER
:
2682 bgType
= BATTLEGROUND_AB
;
2688 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2689 bg
->SendRewardMarkByMail(player
, newitemid
, no_space
);
2693 void Spell::EffectCreateItem(uint32 i
)
2695 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2698 void Spell::EffectCreateItem2(uint32 i
)
2700 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2702 Player
* player
= (Player
*)m_caster
;
2704 uint32 item_id
= m_spellInfo
->EffectItemType
[i
];
2706 DoCreateItem(i
, item_id
);
2708 // special case: fake item replaced by generate using spell_loot_template
2709 if(IsLootCraftingSpell(m_spellInfo
))
2713 if(!player
->HasItemCount(item_id
, 1))
2718 player
->DestroyItemCount(item_id
, count
, true);
2721 // create some random items
2722 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
2726 void Spell::EffectPersistentAA(uint32 i
)
2728 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2730 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2731 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2733 int32 duration
= GetSpellDuration(m_spellInfo
);
2734 DynamicObject
* dynObj
= new DynamicObject
;
2735 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
))
2740 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2741 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2742 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2743 m_caster
->AddDynObject(dynObj
);
2744 dynObj
->GetMap()->Add(dynObj
);
2747 void Spell::EffectEnergize(uint32 i
)
2751 if(!unitTarget
->isAlive())
2754 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2757 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2759 // Some level depends spells
2762 switch (m_spellInfo
->Id
)
2766 level_diff
= m_caster
->getLevel() - 40;
2771 level_diff
= m_caster
->getLevel() - 60;
2776 level_diff
= m_caster
->getLevel() - 60;
2784 damage
-= multiplier
* level_diff
;
2789 if(unitTarget
->GetMaxPower(power
) == 0)
2792 unitTarget
->ModifyPower(power
,damage
);
2793 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2795 // Mad Alchemist's Potion
2796 if (m_spellInfo
->Id
== 45051)
2798 // find elixirs on target
2799 uint32 elixir_mask
= 0;
2800 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2801 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2803 uint32 spell_id
= itr
->second
->GetId();
2804 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2805 elixir_mask
|= mask
;
2808 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2809 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2811 // get all available elixirs by mask and spell level
2812 std::vector
<uint32
> elixirs
;
2813 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2814 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2816 if (itr
->second
& elixir_mask
)
2818 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2821 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2822 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2825 elixirs
.push_back(itr
->first
);
2829 if (!elixirs
.empty())
2831 // cast random elixir on target
2832 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2833 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2838 void Spell::EffectEnergisePct(uint32 i
)
2842 if(!unitTarget
->isAlive())
2845 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2848 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2850 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2854 uint32 gain
= damage
* maxPower
/ 100;
2855 unitTarget
->ModifyPower(power
, gain
);
2856 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2859 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2861 Player
* player
= (Player
*)m_caster
;
2867 if (Script
->GOHello(player
, gameObjTarget
))
2870 switch (gameObjTarget
->GetGoType())
2872 case GAMEOBJECT_TYPE_DOOR
:
2873 case GAMEOBJECT_TYPE_BUTTON
:
2874 gameObjTarget
->UseDoorOrButton();
2875 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2878 case GAMEOBJECT_TYPE_QUESTGIVER
:
2879 // start or end quest
2880 player
->PrepareQuestMenu(guid
);
2881 player
->SendPreparedQuest(guid
);
2884 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2885 // triggering linked GO
2886 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2887 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2890 case GAMEOBJECT_TYPE_GOOBER
:
2891 // goober_scripts can be triggered if the player don't have the quest
2892 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2894 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2895 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2898 // cast goober spell
2899 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2900 ///Quest require to be active for GO using
2901 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2904 gameObjTarget
->AddUniqueUse(player
);
2905 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2907 //TODO? Objective counting called without spell check but with quest objective check
2908 // if send spell id then this line will duplicate to spell casting call (double counting)
2909 // So we or have this line and not required in quest_template have reqSpellIdN
2910 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2911 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2913 // triggering linked GO
2914 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2915 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2919 case GAMEOBJECT_TYPE_CHEST
:
2920 // TODO: possible must be moved to loot release (in different from linked triggering)
2921 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2923 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2924 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2927 // triggering linked GO
2928 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2929 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2931 // Don't return, let loots been taken
2938 player
->SendLoot(guid
, loottype
);
2941 void Spell::EffectOpenLock(uint32 effIndex
)
2943 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2945 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2949 Player
* player
= (Player
*)m_caster
;
2957 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2958 // Arathi Basin banner opening !
2959 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2960 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2962 //CanUseBattleGroundObject() already called in CheckCast()
2963 // in battleground check
2964 if(BattleGround
*bg
= player
->GetBattleGround())
2966 // check if it's correct bg
2967 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2968 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2972 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2974 //CanUseBattleGroundObject() already called in CheckCast()
2975 // in battleground check
2976 if(BattleGround
*bg
= player
->GetBattleGround())
2978 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2979 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2983 lockId
= gameObjTarget
->GetLockId();
2984 guid
= gameObjTarget
->GetGUID();
2988 lockId
= itemTarget
->GetProto()->LockID
;
2989 guid
= itemTarget
->GetGUID();
2993 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2997 SkillType skillId
= SKILL_NONE
;
2998 int32 reqSkillValue
= 0;
3001 SpellCastResult res
= CanOpenLock(effIndex
, lockId
, skillId
, reqSkillValue
, skillValue
);
3002 if(res
!= SPELL_CAST_OK
)
3004 SendCastResult(res
);
3008 SendLoot(guid
, LOOT_SKINNING
);
3010 // not allow use skill grow at item base open
3011 if(!m_CastItem
&& skillId
!= SKILL_NONE
)
3013 // update skill if really known
3014 if(uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3018 // Allow one skill-up until respawned
3019 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3020 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
) )
3021 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3026 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3032 void Spell::EffectSummonChangeItem(uint32 i
)
3034 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3037 Player
*player
= (Player
*)m_caster
;
3039 // applied only to using item
3043 // ... only to item in own inventory/bank/equip_slot
3044 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3047 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3051 uint16 pos
= m_CastItem
->GetPos();
3053 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3057 for(uint8 j
= PERM_ENCHANTMENT_SLOT
; j
<=TEMP_ENCHANTMENT_SLOT
; ++j
)
3059 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)))
3060 pNewItem
->SetEnchantment(EnchantmentSlot(j
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(j
)));
3063 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3065 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3066 player
->DurabilityLoss(pNewItem
, loosePercent
);
3069 if( player
->IsInventoryPos( pos
) )
3071 ItemPosCountVec dest
;
3072 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3073 if( msg
== EQUIP_ERR_OK
)
3075 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3077 // prevent crash at access and unexpected charges counting with item update queue corrupt
3078 if(m_CastItem
==m_targets
.getItemTarget())
3079 m_targets
.setItemTarget(NULL
);
3083 player
->StoreItem( dest
, pNewItem
, true);
3087 else if( player
->IsBankPos ( pos
) )
3089 ItemPosCountVec dest
;
3090 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3091 if( msg
== EQUIP_ERR_OK
)
3093 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3095 // prevent crash at access and unexpected charges counting with item update queue corrupt
3096 if(m_CastItem
==m_targets
.getItemTarget())
3097 m_targets
.setItemTarget(NULL
);
3101 player
->BankItem( dest
, pNewItem
, true);
3105 else if( player
->IsEquipmentPos ( pos
) )
3108 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3109 if( msg
== EQUIP_ERR_OK
)
3111 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3113 // prevent crash at access and unexpected charges counting with item update queue corrupt
3114 if(m_CastItem
==m_targets
.getItemTarget())
3115 m_targets
.setItemTarget(NULL
);
3119 player
->EquipItem( dest
, pNewItem
, true);
3120 player
->AutoUnequipOffhandIfNeed();
3129 void Spell::EffectOpenSecretSafe(uint32 i
)
3131 EffectOpenLock(i
); //no difference for now
3134 void Spell::EffectProficiency(uint32
/*i*/)
3136 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3138 Player
*p_target
= (Player
*)unitTarget
;
3140 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3141 if(m_spellInfo
->EquippedItemClass
== ITEM_CLASS_WEAPON
&& !(p_target
->GetWeaponProficiency() & subClassMask
))
3143 p_target
->AddWeaponProficiency(subClassMask
);
3144 p_target
->SendProficiency(ITEM_CLASS_WEAPON
, p_target
->GetWeaponProficiency());
3146 if(m_spellInfo
->EquippedItemClass
== ITEM_CLASS_ARMOR
&& !(p_target
->GetArmorProficiency() & subClassMask
))
3148 p_target
->AddArmorProficiency(subClassMask
);
3149 p_target
->SendProficiency(ITEM_CLASS_ARMOR
, p_target
->GetArmorProficiency());
3153 void Spell::EffectApplyAreaAura(uint32 i
)
3157 if(!unitTarget
->isAlive())
3160 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3161 unitTarget
->AddAura(Aur
);
3164 void Spell::EffectSummonType(uint32 i
)
3166 switch(m_spellInfo
->EffectMiscValueB
[i
])
3168 case SUMMON_TYPE_GUARDIAN
:
3169 case SUMMON_TYPE_POSESSED
:
3170 case SUMMON_TYPE_POSESSED2
:
3171 case SUMMON_TYPE_FORCE_OF_NATURE
:
3172 case SUMMON_TYPE_GUARDIAN2
:
3173 EffectSummonGuardian(i
);
3175 case SUMMON_TYPE_WILD
:
3176 EffectSummonWild(i
);
3178 case SUMMON_TYPE_DEMON
:
3179 EffectSummonDemon(i
);
3181 case SUMMON_TYPE_SUMMON
:
3184 case SUMMON_TYPE_CRITTER
:
3185 case SUMMON_TYPE_CRITTER2
:
3186 case SUMMON_TYPE_CRITTER3
:
3187 EffectSummonCritter(i
);
3189 case SUMMON_TYPE_TOTEM_SLOT1
:
3190 case SUMMON_TYPE_TOTEM_SLOT2
:
3191 case SUMMON_TYPE_TOTEM_SLOT3
:
3192 case SUMMON_TYPE_TOTEM_SLOT4
:
3193 case SUMMON_TYPE_TOTEM
:
3194 EffectSummonTotem(i
);
3196 case SUMMON_TYPE_UNKNOWN1
:
3197 case SUMMON_TYPE_UNKNOWN2
:
3198 case SUMMON_TYPE_UNKNOWN3
:
3199 case SUMMON_TYPE_UNKNOWN4
:
3200 case SUMMON_TYPE_UNKNOWN5
:
3203 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3208 void Spell::EffectSummon(uint32 i
)
3210 if(m_caster
->GetPetGUID())
3215 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3218 uint32 level
= m_caster
->getLevel();
3219 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3221 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3223 // set timer for unsummon
3224 int32 duration
= GetSpellDuration(m_spellInfo
);
3226 spawnCreature
->SetDuration(duration
);
3231 Map
*map
= m_caster
->GetMap();
3232 uint32 pet_number
= objmgr
.GeneratePetNumber();
3233 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
3234 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3236 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3237 delete spawnCreature
;
3241 // Summon in dest location
3243 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3245 x
= m_targets
.m_destX
;
3246 y
= m_targets
.m_destY
;
3247 z
= m_targets
.m_destZ
;
3250 m_caster
->GetClosePoint(x
, y
, z
, spawnCreature
->GetObjectSize());
3252 spawnCreature
->Relocate(x
, y
, z
, -m_caster
->GetOrientation());
3254 if(!spawnCreature
->IsPositionValid())
3256 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3257 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3258 delete spawnCreature
;
3262 // set timer for unsummon
3263 int32 duration
= GetSpellDuration(m_spellInfo
);
3265 spawnCreature
->SetDuration(duration
);
3267 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3268 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3269 spawnCreature
->setPowerType(POWER_MANA
);
3270 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3271 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3272 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3273 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3274 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3275 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3276 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3277 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3278 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3280 spawnCreature
->InitStatsForLevel(level
);
3282 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3284 spawnCreature
->AIM_Initialize();
3285 spawnCreature
->InitPetCreateSpells();
3286 spawnCreature
->InitLevelupSpellsForLevel();
3287 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3288 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3290 std::string name
= m_caster
->GetName();
3291 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3292 spawnCreature
->SetName( name
);
3294 map
->Add((Creature
*)spawnCreature
);
3296 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3298 m_caster
->SetPet(spawnCreature
);
3299 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3300 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3301 ((Player
*)m_caster
)->PetSpellInitialize();
3305 void Spell::EffectLearnSpell(uint32 i
)
3310 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3312 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3313 EffectLearnPetSpell(i
);
3318 Player
*player
= (Player
*)unitTarget
;
3320 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3321 player
->learnSpell(spellToLearn
,false);
3323 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3326 void Spell::EffectDispel(uint32 i
)
3331 // Fill possible dispell list
3332 std::vector
<Aura
*> dispel_list
;
3334 // Create dispel mask by dispel type
3335 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3336 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3337 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3338 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3340 Aura
*aur
= (*itr
).second
;
3341 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3343 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3345 bool positive
= true;
3346 if (!aur
->IsPositive())
3349 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3351 // do not remove positive auras if friendly target
3352 // negative auras if non-friendly target
3353 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3356 // Add aura to dispel list
3357 dispel_list
.push_back(aur
);
3360 // Ok if exist some buffs for dispel try dispel it
3361 if (!dispel_list
.empty())
3363 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3364 std::list
< uint32
> fail_list
; // spell_id
3365 int32 list_size
= dispel_list
.size();
3366 // Dispell N = damage buffs (or while exist buffs for dispel)
3367 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3369 // Random select buff for dispel
3370 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3372 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3373 // Base dispel chance
3374 // TODO: possible chance depend from spell level??
3375 int32 miss_chance
= 0;
3376 // Apply dispel mod from aura caster
3377 if (Unit
*caster
= aur
->GetCaster())
3379 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3380 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3383 if (roll_chance_i(miss_chance
))
3384 fail_list
.push_back(aur
->GetId());
3386 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3387 // Remove buff from list for prevent doubles
3388 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3390 Aura
*dispeled
= *j
;
3391 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3393 j
= dispel_list
.erase(j
);
3400 // Send success log and really remove auras
3401 if (!success_list
.empty())
3403 int32 count
= success_list
.size();
3404 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3405 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3406 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3407 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3408 data
<< uint8(0); // not used
3409 data
<< uint32(count
); // count
3410 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3412 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3413 data
<< uint32(spellInfo
->Id
); // Spell Id
3414 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3415 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3417 m_caster
->SendMessageToSet(&data
, true);
3421 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3423 uint32 heal_spell
= 0;
3424 switch (m_spellInfo
->Id
)
3426 case 19505: heal_spell
= 19658; break;
3427 case 19731: heal_spell
= 19732; break;
3428 case 19734: heal_spell
= 19733; break;
3429 case 19736: heal_spell
= 19735; break;
3430 case 27276: heal_spell
= 27278; break;
3431 case 27277: heal_spell
= 27279; break;
3433 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3437 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3440 // Send fail log to client
3441 if (!fail_list
.empty())
3443 // Failed to dispell
3444 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3445 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3446 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3447 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3448 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3449 data
<< uint32(*j
); // Spell Id
3450 m_caster
->SendMessageToSet(&data
, true);
3455 void Spell::EffectDualWield(uint32
/*i*/)
3457 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3458 ((Player
*)unitTarget
)->SetCanDualWield(true);
3461 void Spell::EffectPull(uint32
/*i*/)
3463 // TODO: create a proper pull towards distract spell center for distract
3464 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3467 void Spell::EffectDistract(uint32
/*i*/)
3469 // Check for possible target
3470 if (!unitTarget
|| unitTarget
->isInCombat())
3473 // target must be OK to do this
3474 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3477 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3479 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3481 // For players just turn them
3483 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3484 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3485 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3489 // Set creature Distracted, Stop it, And turn it
3490 unitTarget
->SetOrientation(angle
);
3491 unitTarget
->StopMoving();
3492 unitTarget
->GetMotionMaster()->MoveDistract(damage
* IN_MILISECONDS
);
3496 void Spell::EffectPickPocket(uint32
/*i*/)
3498 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3501 // victim must be creature and attackable
3502 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3505 // victim have to be alive and humanoid or undead
3506 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3508 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3510 if (chance
> irand(0, 19))
3512 // Stealing successful
3513 //sLog.outDebug("Sending loot from pickpocket");
3514 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3518 // Reveal action + get attack
3519 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3520 if (((Creature
*)unitTarget
)->AI())
3521 ((Creature
*)unitTarget
)->AI()->AttackedBy(m_caster
);
3526 void Spell::EffectAddFarsight(uint32 i
)
3528 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3529 int32 duration
= GetSpellDuration(m_spellInfo
);
3530 DynamicObject
* dynObj
= new DynamicObject
;
3531 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
))
3536 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3537 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3538 m_caster
->AddDynObject(dynObj
);
3539 dynObj
->GetMap()->Add(dynObj
);
3540 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3541 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3544 void Spell::EffectSummonWild(uint32 i
)
3546 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3550 uint32 level
= m_caster
->getLevel();
3552 // level of creature summoned using engineering item based at engineering skill level
3553 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3555 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3556 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3558 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3566 // select center of summon position
3567 float center_x
= m_targets
.m_destX
;
3568 float center_y
= m_targets
.m_destY
;
3569 float center_z
= m_targets
.m_destZ
;
3571 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3573 int32 amount
= damage
> 0 ? damage
: 1;
3575 for(int32 count
= 0; count
< amount
; ++count
)
3578 // If dest location if present
3579 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3581 // Summon 1 unit in dest location
3584 px
= m_targets
.m_destX
;
3585 py
= m_targets
.m_destY
;
3586 pz
= m_targets
.m_destZ
;
3588 // Summon in random point all other units if location present
3590 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3592 // Summon if dest location not present near caster
3594 m_caster
->GetClosePoint(px
, py
, pz
, 3.0f
);
3596 int32 duration
= GetSpellDuration(m_spellInfo
);
3598 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3600 m_caster
->SummonCreature(creature_entry
, px
, py
, pz
, m_caster
->GetOrientation(), summonType
, duration
);
3604 void Spell::EffectSummonGuardian(uint32 i
)
3606 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3610 // Jewelery statue case (totem like)
3611 if(m_spellInfo
->SpellIconID
== 2056)
3613 EffectSummonTotem(i
);
3617 // set timer for unsummon
3618 int32 duration
= GetSpellDuration(m_spellInfo
);
3620 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3621 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3622 // so this code hack in fact
3623 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
) == 0) )
3624 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3625 return; // find old guardian, ignore summon
3627 // in another case summon new
3628 uint32 level
= m_caster
->getLevel();
3630 // level of pet summoned using engineering item based at engineering skill level
3631 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& m_CastItem
)
3633 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3634 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3636 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3639 level
= skill202
/ 5;
3644 // select center of summon position
3645 float center_x
= m_targets
.m_destX
;
3646 float center_y
= m_targets
.m_destY
;
3647 float center_z
= m_targets
.m_destZ
;
3649 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3651 int32 amount
= damage
> 0 ? damage
: 1;
3653 for(int32 count
= 0; count
< amount
; ++count
)
3655 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3657 Map
*map
= m_caster
->GetMap();
3658 uint32 pet_number
= objmgr
.GeneratePetNumber();
3659 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3660 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3662 sLog
.outError("no such creature entry %u", m_spellInfo
->EffectMiscValue
[i
]);
3663 delete spawnCreature
;
3668 // If dest location if present
3669 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3671 // Summon 1 unit in dest location
3674 px
= m_targets
.m_destX
;
3675 py
= m_targets
.m_destY
;
3676 pz
= m_targets
.m_destZ
;
3678 // Summon in random point all other units if location present
3680 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3682 // Summon if dest location not present near caster
3684 m_caster
->GetClosePoint(px
, py
, pz
,spawnCreature
->GetObjectSize());
3686 spawnCreature
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
3688 if(!spawnCreature
->IsPositionValid())
3690 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3691 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3692 delete spawnCreature
;
3697 spawnCreature
->SetDuration(duration
);
3699 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3700 spawnCreature
->setPowerType(POWER_MANA
);
3701 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3702 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3703 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3704 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3705 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3706 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3707 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3709 spawnCreature
->InitStatsForLevel(level
);
3710 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3712 spawnCreature
->AIM_Initialize();
3714 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3715 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3717 map
->Add((Creature
*)spawnCreature
);
3721 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3726 if(unitTarget
->isInFlight())
3729 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3732 m_caster
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
3734 unitTarget
->NearTeleportTo(fx
, fy
, fz
, -m_caster
->GetOrientation(), unitTarget
==m_caster
);
3737 void Spell::EffectLearnSkill(uint32 i
)
3739 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3745 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3746 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3747 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
? skillval
: 1, damage
* 75);
3750 void Spell::EffectAddHonor(uint32
/*i*/)
3752 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3755 // not scale value for item based reward (/10 value expected)
3758 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/ 10);
3759 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo
->Id
, damage
/10, m_CastItem
->GetEntry(),((Player
*)unitTarget
)->GetGUIDLow());
3763 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3766 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
3767 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
3768 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
3772 //maybe we have correct honor_gain in damage already
3773 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3774 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3778 void Spell::EffectTradeSkill(uint32
/*i*/)
3780 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3782 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3783 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3784 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3787 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3789 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3794 Player
* p_caster
= (Player
*)m_caster
;
3796 // not grow at item use at item case
3797 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3799 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3803 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3807 // item can be in trade slot and have owner diff. from caster
3808 Player
* item_owner
= itemTarget
->GetOwner();
3812 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3814 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3815 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3816 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3817 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3820 // remove old enchanting before applying new if equipped
3821 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3823 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3825 // add new enchanting if equipped
3826 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3829 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3831 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3836 Player
* p_caster
= (Player
*)m_caster
;
3838 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3842 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3846 // support only enchantings with add socket in this slot
3848 bool add_socket
= false;
3849 for(int i
= 0; i
< 3; ++i
)
3851 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3859 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.",
3860 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3865 // item can be in trade slot and have owner diff. from caster
3866 Player
* item_owner
= itemTarget
->GetOwner();
3870 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3872 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3873 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3874 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3875 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3878 // remove old enchanting before applying new if equipped
3879 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3881 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3883 // add new enchanting if equipped
3884 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3887 void Spell::EffectEnchantItemTmp(uint32 i
)
3889 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3892 Player
* p_caster
= (Player
*)m_caster
;
3897 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3899 // Shaman Rockbiter Weapon
3900 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3902 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3904 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3905 // with already applied percent bonus from Elemental Weapons talent
3906 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3907 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3908 switch(enchnting_damage
)
3911 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3913 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3914 case 5: enchant_id
= 3025; break; // 20%
3916 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3917 case 7: enchant_id
= 3027; break; // 20%
3919 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3920 case 10: enchant_id
= 503; break; // 14%
3921 case 11: enchant_id
= 3031; break; // 20%
3923 case 15: enchant_id
= 3035; break; // 0%
3924 case 16: enchant_id
= 1663; break; // 7%
3925 case 17: enchant_id
= 3033; break; // 14%
3926 case 18: enchant_id
= 3034; break; // 20%
3928 case 28: enchant_id
= 3038; break; // 0%
3929 case 29: enchant_id
= 683; break; // 7%
3930 case 31: enchant_id
= 3036; break; // 14%
3931 case 33: enchant_id
= 3037; break; // 20%
3933 case 40: enchant_id
= 3041; break; // 0%
3934 case 42: enchant_id
= 1664; break; // 7%
3935 case 45: enchant_id
= 3039; break; // 14%
3936 case 48: enchant_id
= 3040; break; // 20%
3938 case 49: enchant_id
= 3044; break; // 0%
3939 case 52: enchant_id
= 2632; break; // 7%
3940 case 55: enchant_id
= 3042; break; // 14%
3941 case 58: enchant_id
= 3043; break; // 20%
3943 case 62: enchant_id
= 2633; break; // 0%
3944 case 66: enchant_id
= 3018; break; // 7%
3945 case 70: enchant_id
= 3019; break; // 14%
3946 case 74: enchant_id
= 3020; break; // 20%
3948 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3955 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3959 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3962 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3966 // select enchantment duration
3969 // rogue family enchantments exception by duration
3970 if(m_spellInfo
->Id
== 38615)
3971 duration
= 1800; // 30 mins
3972 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3973 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
3974 duration
= 3600; // 1 hour
3975 // shaman family enchantments
3976 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
3977 duration
= 1800; // 30 mins
3978 // other cases with this SpellVisual already selected
3979 else if(m_spellInfo
->SpellVisual
[0] == 215)
3980 duration
= 1800; // 30 mins
3981 // some fishing pole bonuses
3982 else if(m_spellInfo
->SpellVisual
[0] == 563)
3983 duration
= 600; // 10 mins
3984 // shaman rockbiter enchantments
3985 else if(m_spellInfo
->SpellVisual
[0] == 0)
3986 duration
= 1800; // 30 mins
3987 else if(m_spellInfo
->Id
== 29702)
3988 duration
= 300; // 5 mins
3989 else if(m_spellInfo
->Id
== 37360)
3990 duration
= 300; // 5 mins
3993 duration
= 3600; // 1 hour
3995 // item can be in trade slot and have owner diff. from caster
3996 Player
* item_owner
= itemTarget
->GetOwner();
4000 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4002 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4003 p_caster
->GetName(), p_caster
->GetSession()->GetAccountId(),
4004 itemTarget
->GetProto()->Name1
, itemTarget
->GetEntry(),
4005 item_owner
->GetName(), item_owner
->GetSession()->GetAccountId());
4008 // remove old enchanting before applying new if equipped
4009 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
, false);
4011 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
* 1000, 0);
4013 // add new enchanting if equipped
4014 item_owner
->ApplyEnchantment(itemTarget
, TEMP_ENCHANTMENT_SLOT
, true);
4017 void Spell::EffectTameCreature(uint32
/*i*/)
4019 if(m_caster
->GetPetGUID())
4025 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4028 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4030 if(creatureTarget
->isPet())
4033 if(m_caster
->getClass() != CLASS_HUNTER
)
4036 // cast finish successfully
4037 //SendChannelUpdate(0);
4040 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4042 // kill original creature
4043 creatureTarget
->setDeathState(JUST_DIED
);
4044 creatureTarget
->RemoveCorpse();
4045 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4047 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4049 // prepare visual effect for levelup
4050 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4053 pet
->GetMap()->Add((Creature
*)pet
);
4055 // visual effect for levelup
4056 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4058 // caster have pet now
4059 m_caster
->SetPet(pet
);
4061 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4063 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4064 ((Player
*)m_caster
)->PetSpellInitialize();
4068 void Spell::EffectSummonPet(uint32 i
)
4070 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4072 Pet
*OldSummon
= m_caster
->GetPet();
4074 // if pet requested type already exist
4077 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4079 // pet in corpse state can't be summoned
4080 if( OldSummon
->isDead() )
4083 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4084 OldSummon
->SetMapId(m_caster
->GetMapId());
4087 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4089 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4090 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4092 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4094 ((Player
*)m_caster
)->PetSpellInitialize();
4099 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4100 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4105 Pet
* NewSummon
= new Pet
;
4107 // petentry==0 for hunter "call pet" (current pet summoned if any)
4108 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4110 if(NewSummon
->getPetType()==SUMMON_PET
)
4112 // Remove Demonic Sacrifice auras (known pet)
4113 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4114 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4116 if((*itr
)->GetModifier()->m_miscvalue
== 2228)
4118 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4119 itr
= auraClassScripts
.begin();
4129 // not error in case fail hunter call pet
4136 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4140 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4145 Map
*map
= m_caster
->GetMap();
4146 uint32 pet_number
= objmgr
.GeneratePetNumber();
4147 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4148 petentry
, pet_number
))
4155 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4157 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4159 if(!NewSummon
->IsPositionValid())
4161 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4162 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4167 uint32 petlevel
= m_caster
->getLevel();
4168 NewSummon
->setPetType(SUMMON_PET
);
4170 uint32 faction
= m_caster
->getFaction();
4171 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4173 if ( ((Creature
*)m_caster
)->isTotem() )
4174 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4176 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4179 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4180 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4181 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4182 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4183 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4184 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4185 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4186 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4187 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4188 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4190 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4191 // this enables pet details window (Shift+P)
4193 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4194 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4195 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4197 if(m_caster
->IsPvP())
4198 NewSummon
->SetPvP(true);
4200 NewSummon
->InitStatsForLevel(petlevel
);
4201 NewSummon
->InitPetCreateSpells();
4202 NewSummon
->InitLevelupSpellsForLevel();
4203 NewSummon
->InitTalentForLevel();
4205 if(NewSummon
->getPetType()==SUMMON_PET
)
4207 // Remove Demonic Sacrifice auras (new pet)
4208 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4209 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4211 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4213 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4214 itr
= auraClassScripts
.begin();
4220 // generate new name for summon pet
4221 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4222 if(!new_name
.empty())
4223 NewSummon
->SetName(new_name
);
4225 else if(NewSummon
->getPetType()==HUNTER_PET
)
4226 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4228 NewSummon
->AIM_Initialize();
4229 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4230 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4232 map
->Add((Creature
*)NewSummon
);
4234 m_caster
->SetPet(NewSummon
);
4235 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4237 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4239 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4240 ((Player
*)m_caster
)->PetSpellInitialize();
4244 void Spell::EffectLearnPetSpell(uint32 i
)
4246 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4249 Player
*_player
= (Player
*)m_caster
;
4251 Pet
*pet
= _player
->GetPet();
4257 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4258 if(!learn_spellproto
)
4261 pet
->learnSpell(learn_spellproto
->Id
);
4263 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4264 _player
->PetSpellInitialize();
4267 void Spell::EffectTaunt(uint32
/*i*/)
4272 // this effect use before aura Taunt apply for prevent taunt already attacking target
4273 // for spell as marked "non effective at already attacking target"
4274 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4276 if (unitTarget
->getVictim()==m_caster
)
4278 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4283 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4284 if (unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4285 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4288 void Spell::EffectWeaponDmg(uint32 i
)
4292 if(!unitTarget
->isAlive())
4295 // multiple weapon dmg effect workaround
4296 // execute only the last weapon damage
4297 // and handle all effects at once
4298 for (int j
= 0; j
< 3; ++j
)
4300 switch(m_spellInfo
->Effect
[j
])
4302 case SPELL_EFFECT_WEAPON_DAMAGE
:
4303 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4304 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4305 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4306 if (j
< i
) // we must calculate only at last weapon effect
4312 // some spell specific modifiers
4313 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4315 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4316 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4317 bool normalized
= false;
4319 int32 spell_bonus
= 0; // bonus specific for spell
4320 switch(m_spellInfo
->SpellFamilyName
)
4322 case SPELLFAMILY_WARRIOR
:
4324 // Whirlwind, single only spell with 2 weapon white damage apply if have
4325 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4327 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4328 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4330 // Devastate bonus and sunder armor refresh
4331 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4334 // Need refresh all Sunder Armor auras from this caster
4335 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4336 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4338 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4339 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4340 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4341 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4343 (*itr
).second
->RefreshAura();
4344 stack
= (*itr
).second
->GetStackAmount();
4348 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4352 case SPELLFAMILY_ROGUE
:
4354 // Mutilate (for each hand)
4355 if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4359 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4364 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4365 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4367 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4376 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4380 case SPELLFAMILY_PALADIN
:
4382 // Seal of Command - receive benefit from Spell Damage and Healing
4383 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4385 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4386 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4387 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4391 case SPELLFAMILY_SHAMAN
:
4393 // Skyshatter Harness item set bonus
4395 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4397 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4398 for(Unit::AuraList::const_iterator citr
= m_OverrideClassScript
.begin(); citr
!= m_OverrideClassScript
.end(); ++citr
)
4400 // Stormstrike AP Buff
4401 if ( (*citr
)->GetModifier()->m_miscvalue
== 5634 )
4403 m_caster
->CastSpell(m_caster
, 38430, true, NULL
, *citr
);
4411 int32 fixed_bonus
= 0;
4412 for (int j
= 0; j
< 3; ++j
)
4414 switch(m_spellInfo
->Effect
[j
])
4416 case SPELL_EFFECT_WEAPON_DAMAGE
:
4417 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4418 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4420 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4421 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4424 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4425 weaponDamagePercentMod
*= float(CalculateDamage(j
, unitTarget
)) / 100.0f
;
4427 // applied only to prev.effects fixed damage
4428 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4431 break; // not weapon damage effect, just skip
4435 // apply weaponDamagePercentMod to spell bonus also
4436 if(spellBonusNeedWeaponDamagePercentMod
)
4437 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4439 // non-weapon damage
4440 int32 bonus
= spell_bonus
+ fixed_bonus
;
4442 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4446 switch(m_attackType
)
4449 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4450 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4451 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4454 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4455 bonus
= int32(bonus
*weapon_total_pct
);
4458 // + weapon damage with applied weapon% dmg to base weapon damage in call
4459 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4462 bonus
= int32(bonus
*totalDamagePercentMod
);
4464 // prevent negative damage
4465 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4467 // Add melee damage bonuses (also check for negative)
4468 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4469 m_damage
+= eff_damage
;
4472 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4474 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4475 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4479 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4481 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4482 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4486 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4488 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4490 // wands don't have ammo
4491 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_WAND
)
4494 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4496 if(pItem
->GetMaxStackCount()==1)
4498 // decrease durability for non-stackable throw weapon
4499 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4503 // decrease items amount for stackable throw weapon
4505 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4508 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4509 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4513 void Spell::EffectThreat(uint32
/*i*/)
4515 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4518 if(!unitTarget
->CanHaveThreatList())
4521 unitTarget
->AddThreat(m_caster
, float(damage
));
4524 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4528 if(!unitTarget
->isAlive())
4531 uint32 heal
= m_caster
->GetMaxHealth();
4536 void Spell::EffectInterruptCast(uint32
/*i*/)
4540 if(!unitTarget
->isAlive())
4543 // TODO: not all spells that used this effect apply cooldown at school spells
4544 // also exist case: apply cooldown to interrupted cast only and to all spells
4545 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4547 if (unitTarget
->m_currentSpells
[i
])
4549 // check if we can interrupt spell
4550 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4552 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4553 unitTarget
->InterruptSpell(i
,false);
4559 void Spell::EffectSummonObjectWild(uint32 i
)
4561 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4563 GameObject
* pGameObj
= new GameObject
;
4565 WorldObject
* target
= focusObject
;
4570 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4572 x
= m_targets
.m_destX
;
4573 y
= m_targets
.m_destY
;
4574 z
= m_targets
.m_destZ
;
4577 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
4579 Map
*map
= target
->GetMap();
4581 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4582 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4588 int32 duration
= GetSpellDuration(m_spellInfo
);
4589 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4590 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4592 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4593 m_caster
->AddGameObject(pGameObj
);
4596 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4598 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4600 Player
*pl
= (Player
*)m_caster
;
4601 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4602 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4604 uint32 team
= ALLIANCE
;
4606 if(pl
->GetTeam() == team
)
4609 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4614 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4616 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4618 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4619 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4621 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4626 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4628 GameObject
* linkedGO
= new GameObject
;
4629 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4630 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4632 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4633 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4635 m_caster
->AddGameObject(linkedGO
);
4647 void Spell::EffectScriptEffect(uint32 effIndex
)
4649 // TODO: we must implement hunter pet summon at login there (spell 6962)
4651 switch(m_spellInfo
->SpellFamilyName
)
4653 case SPELLFAMILY_GENERIC
:
4655 switch(m_spellInfo
->Id
)
4657 // PX-238 Winter Wondervolt TRAP
4660 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4663 for(int j
= 0; j
< 4; ++j
)
4664 if(unitTarget
->HasAura(spells
[j
],0))
4668 uint32 iTmpSpellId
= spells
[urand(0,3)];
4671 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4677 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4680 uint32 spell_id
= 0;
4683 case 1: spell_id
= 8854; break;
4684 default: spell_id
= 8855; break;
4687 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4690 // Brittle Armor - need remove one 24575 Brittle Armor aura
4692 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4694 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4696 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4698 // Orb teleport spells
4712 switch(m_spellInfo
->Id
)
4714 case 25140: spellid
= 32571; break;
4715 case 25143: spellid
= 32572; break;
4716 case 25650: spellid
= 30140; break;
4717 case 25652: spellid
= 30141; break;
4718 case 29128: spellid
= 32568; break;
4719 case 29129: spellid
= 32569; break;
4720 case 35376: spellid
= 25649; break;
4721 case 35727: spellid
= 35730; break;
4726 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4729 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4744 if(!unitTarget
|| !unitTarget
->isAlive())
4747 // Onyxia Scale Cloak
4748 if(unitTarget
->GetDummyAura(22683))
4752 m_caster
->CastSpell(unitTarget
, 22682, true);
4755 // Summon Black Qiraji Battle Tank
4761 // Prevent stacking of mounts
4762 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4764 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4765 if (unitTarget
->GetAreaId() == 3428)
4766 unitTarget
->CastSpell(unitTarget
, 25863, false);
4768 unitTarget
->CastSpell(unitTarget
, 26655, false);
4771 // Piccolo of the Flaming Fire
4774 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4776 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4782 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4783 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4786 // Mirren's Drinking Hat
4790 switch ( urand(1, 6) )
4795 item
= 23584; break; // Loch Modan Lager
4798 item
= 23585; break; // Stouthammer Lite
4800 item
= 23586; break; // Aerie Peak Pale Ale
4803 DoCreateItem(effIndex
,item
);
4809 // Removes snares and roots.
4810 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4811 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4812 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4816 Aura
*aur
= iter
->second
;
4817 if (!aur
->IsPositive()) //only remove negative spells
4819 // check for mechanic mask
4820 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4822 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4826 next
= Auras
.begin();
4838 unitTarget
->CastSpell(unitTarget
, 41131, true);
4841 // Force Cast - Portal Effect: Sunwell Isle
4847 unitTarget
->CastSpell(unitTarget
, 44870, true);
4850 // Goblin Weather Machine
4859 case 0: spellId
= 46740; break;
4860 case 1: spellId
= 46739; break;
4861 case 2: spellId
= 46738; break;
4862 case 3: spellId
= 46736; break;
4864 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4870 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4873 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4877 // Emblazon Runeblade
4883 unitTarget
->CastSpell(unitTarget
, 51771, false);
4889 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4891 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4892 unitTarget
->CastSpell(unitTarget
, damage
, false);
4895 // Winged Steed of the Ebon Blade
4898 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4901 // Prevent stacking of mounts
4902 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4904 // Triggered spell id dependent of riding skill
4905 if(uint16 skillval
= ((Player
*)unitTarget
)->GetSkillValue(SKILL_RIDING
))
4907 if (skillval
>= 300)
4908 unitTarget
->CastSpell(unitTarget
, 54727, true);
4910 unitTarget
->CastSpell(unitTarget
, 54726, true);
4914 case 58418: // Portal to Orgrimmar
4915 case 58420: // Portal to Stormwind
4917 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
4920 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
4921 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
4923 if (((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
))
4924 unitTarget
->CastSpell(unitTarget
, spellID
, true);
4928 case 59317: // Teleporting
4929 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4933 if (((Player
*)unitTarget
)->GetAreaId() == 4637)
4934 unitTarget
->CastSpell(unitTarget
, 59316, true);
4937 unitTarget
->CastSpell(unitTarget
, 59314, true);
4940 // random spell learn instead placeholder
4941 case 60893: // Northrend Alchemy Research
4942 case 61177: // Northrend Inscription Research
4943 case 61288: // Minor Inscription Research
4944 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4946 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4949 // learn random explicit discovery recipe (if any)
4950 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, (Player
*)m_caster
))
4951 ((Player
*)m_caster
)->learnSpell(discoveredSpell
, false);
4957 case SPELLFAMILY_WARLOCK
:
4959 switch(m_spellInfo
->Id
)
4961 // Healthstone creating spells
4973 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4974 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4976 if((*i
)->GetId() == 18692)
4981 else if((*i
)->GetId() == 18693)
4988 static uint32
const itypes
[8][3] = {
4989 { 5512, 19004, 19005}, // Minor Healthstone
4990 { 5511, 19006, 19007}, // Lesser Healthstone
4991 { 5509, 19008, 19009}, // Healthstone
4992 { 5510, 19010, 19011}, // Greater Healthstone
4993 { 9421, 19012, 19013}, // Major Healthstone
4994 {22103, 22104, 22105}, // Master Healthstone
4995 {36889, 36890, 36891}, // Demonic Healthstone
4996 {36892, 36893, 36894} // Fel Healthstone
4999 switch(m_spellInfo
->Id
)
5002 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
5004 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
5006 itemtype
=itypes
[2][rank
];break; // Healthstone
5008 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
5010 itemtype
=itypes
[4][rank
];break; // Major Healthstone
5012 itemtype
=itypes
[5][rank
];break; // Master Healthstone
5014 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
5016 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
5020 DoCreateItem( effIndex
, itemtype
);
5023 // Everlasting Affliction
5026 // Need refresh caster corruption auras on target
5027 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
5028 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
5030 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5031 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
5032 spellInfo
->SpellFamilyFlags
& 0x0000000000000002LL
&&
5033 (*itr
).second
->GetCasterGUID()==m_caster
->GetGUID())
5034 (*itr
).second
->RefreshAura();
5041 case SPELLFAMILY_PRIEST
:
5043 switch(m_spellInfo
->Id
)
5045 // Pain and Suffering
5050 // Refresh Shadow Word: Pain on target
5051 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5052 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5054 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5055 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5056 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
5057 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5059 (*itr
).second
->RefreshAura();
5070 case SPELLFAMILY_HUNTER
:
5072 switch(m_spellInfo
->Id
)
5078 int32 basePoint
= 0;
5079 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5080 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5082 Aura
*aura
= (*i
).second
;
5083 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5085 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5086 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5087 if (!(familyFlag
& 0x000000800000C000LL
))
5089 // Refresh aura duration
5090 aura
->RefreshAura();
5092 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5093 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5095 spellId
= 53353; // 53353 Chimera Shot - Serpent
5096 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5098 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5099 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5101 spellId
= 53358; // 53358 Chimera Shot - Viper
5102 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5104 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5105 if (familyFlag
& 0x0000000000008000LL
)
5106 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5107 // ?? nothing say in spell desc (possibly need addition check)
5108 //if (familyFlag & 0x0000010000000000LL || // dot
5109 // familyFlag & 0x0000100000000000LL) // stun
5111 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5115 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5123 case SPELLFAMILY_PALADIN
:
5126 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5128 if(!unitTarget
|| !unitTarget
->isAlive())
5130 uint32 spellId1
= 0;
5131 uint32 spellId2
= 0;
5133 // Judgement self add switch
5134 switch (m_spellInfo
->Id
)
5136 case 41467: break; // Judgement
5137 case 53407: spellId1
= 20184; break; // Judgement of Justice
5138 case 20271: // Judgement of Light
5139 case 57774: spellId1
= 20185; break; // Judgement of Light
5140 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5144 // all seals have aura dummy in 2 effect
5145 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5146 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5148 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5149 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5150 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5152 spellId2
= (*itr
)->GetModifier()->m_amount
;
5153 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5159 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5161 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5165 case SPELLFAMILY_POTION
:
5167 switch(m_spellInfo
->Id
)
5174 unitTarget
->CastSpell(unitTarget
, 28694, true);
5182 // 25% chance of casting a random buff
5183 if(roll_chance_i(75))
5186 // triggered spells are 28703 to 28707
5187 // Note: some sources say, that there was the possibility of
5188 // receiving a debuff. However, this seems to be removed by a patch.
5189 const uint32 spellid
= 28703;
5191 // don't overwrite an existing aura
5192 for(uint8 i
= 0; i
< 5; ++i
)
5193 if(unitTarget
->HasAura(spellid
+ i
, 0))
5195 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5204 // 25% chance of casting Nightmare Pollen
5205 if(roll_chance_i(75))
5207 unitTarget
->CastSpell(unitTarget
, 28721, true);
5215 // normal DB scripted effect
5219 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5220 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5223 void Spell::EffectSanctuary(uint32
/*i*/)
5227 //unitTarget->CombatStop();
5229 unitTarget
->CombatStop();
5230 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5231 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5232 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5234 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5238 void Spell::EffectAddComboPoints(uint32
/*i*/)
5243 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5249 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5252 void Spell::EffectDuel(uint32 i
)
5254 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5257 Player
*caster
= (Player
*)m_caster
;
5258 Player
*target
= (Player
*)unitTarget
;
5260 // caster or target already have requested duel
5261 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5264 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5265 // Don't have to check the target's map since you cannot challenge someone across maps
5266 uint32 mapid
= caster
->GetMapId();
5267 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5269 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5273 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5274 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5276 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5280 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5281 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5283 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5287 //CREATE DUEL FLAG OBJECT
5288 GameObject
* pGameObj
= new GameObject
;
5290 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5292 Map
*map
= m_caster
->GetMap();
5293 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5294 map
, m_caster
->GetPhaseMask(),
5295 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5296 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5297 m_caster
->GetPositionZ(),
5298 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
5304 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5305 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5306 int32 duration
= GetSpellDuration(m_spellInfo
);
5307 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5308 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5310 m_caster
->AddGameObject(pGameObj
);
5315 WorldPacket
data(SMSG_DUEL_REQUESTED
, 8 + 8);
5316 data
<< uint64(pGameObj
->GetGUID());
5317 data
<< uint64(caster
->GetGUID());
5318 caster
->GetSession()->SendPacket(&data
);
5319 target
->GetSession()->SendPacket(&data
);
5322 DuelInfo
*duel
= new DuelInfo
;
5323 duel
->initiator
= caster
;
5324 duel
->opponent
= target
;
5325 duel
->startTime
= 0;
5326 duel
->startTimer
= 0;
5327 caster
->duel
= duel
;
5329 DuelInfo
*duel2
= new DuelInfo
;
5330 duel2
->initiator
= caster
;
5331 duel2
->opponent
= caster
;
5332 duel2
->startTime
= 0;
5333 duel2
->startTimer
= 0;
5334 target
->duel
= duel2
;
5336 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5337 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5340 void Spell::EffectStuck(uint32
/*i*/)
5342 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5345 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5348 Player
* pTarget
= (Player
*)unitTarget
;
5350 sLog
.outDebug("Spell Effect: Stuck");
5351 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());
5353 if(pTarget
->isInFlight())
5356 // homebind location is loaded always
5357 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5359 // Stuck spell trigger Hearthstone cooldown
5360 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5363 Spell
spell(pTarget
, spellInfo
, true, 0);
5364 spell
.SendSpellCooldown();
5367 void Spell::EffectSummonPlayer(uint32
/*i*/)
5369 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5372 // Evil Twin (ignore player summon, but hide this for summoner)
5373 if(unitTarget
->GetDummyAura(23445))
5377 m_caster
->GetClosePoint(x
, y
, z
, unitTarget
->GetObjectSize());
5379 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5381 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5382 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5383 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5384 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5385 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5388 static ScriptInfo
generateActivateCommand()
5391 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5395 void Spell::EffectActivateObject(uint32 effect_idx
)
5400 static ScriptInfo activateCommand
= generateActivateCommand();
5402 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5404 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5407 void Spell::EffectApplyGlyph(uint32 i
)
5409 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5412 Player
*player
= (Player
*)m_caster
;
5415 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5417 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5419 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5421 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5423 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5424 return; // glyph slot mismatch
5429 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5431 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5433 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5434 player
->SetGlyph(m_glyphIndex
, 0);
5438 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5439 player
->SetGlyph(m_glyphIndex
, glyph
);
5444 void Spell::EffectSummonTotem(uint32 i
)
5447 switch(m_spellInfo
->EffectMiscValueB
[i
])
5449 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5450 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5451 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5452 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5453 // Battle standard case
5454 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5455 // jewelery statue case, like totem without slot
5456 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5460 if(slot
< MAX_TOTEM
)
5462 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5465 Creature
*OldTotem
= m_caster
->GetMap()->GetCreature(guid
);
5466 if(OldTotem
&& OldTotem
->isTotem())
5467 ((Totem
*)OldTotem
)->UnSummon();
5472 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5473 team
= ((Player
*)m_caster
)->GetTeam();
5475 Totem
* pTotem
= new Totem
;
5477 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5478 m_spellInfo
->EffectMiscValue
[i
], team
))
5484 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5487 m_caster
->GetClosePoint(x
, y
, z
, pTotem
->GetObjectSize(), 2.0f
, angle
);
5489 // totem must be at same Z in case swimming caster and etc.
5490 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5491 z
= m_caster
->GetPositionZ();
5493 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5495 if(slot
< MAX_TOTEM
)
5496 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5498 pTotem
->SetOwner(m_caster
->GetGUID());
5499 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5501 int32 duration
=GetSpellDuration(m_spellInfo
);
5502 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5503 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
5504 pTotem
->SetDuration(duration
);
5506 if (damage
) // if not spell info, DB values used
5508 pTotem
->SetMaxHealth(damage
);
5509 pTotem
->SetHealth(damage
);
5512 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5514 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5515 pTotem
->SetFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_PVP_ATTACKABLE
);
5517 if(m_caster
->IsPvP())
5518 pTotem
->SetPvP(true);
5520 pTotem
->Summon(m_caster
);
5522 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5524 WorldPacket
data(SMSG_TOTEM_CREATED
, 1 + 8 + 4 + 4);
5525 data
<< uint8(slot
);
5526 data
<< uint64(pTotem
->GetGUID());
5527 data
<< uint32(duration
);
5528 data
<< uint32(m_spellInfo
->Id
);
5529 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5533 void Spell::EffectEnchantHeldItem(uint32 i
)
5535 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5536 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5539 Player
* item_owner
= (Player
*)unitTarget
;
5540 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5546 if(!item
->IsEquipped())
5549 if (m_spellInfo
->EffectMiscValue
[i
])
5551 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5552 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5554 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5556 duration
= 10; //10 seconds for enchants which don't have listed duration
5558 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5562 // Always go to temp enchantment slot
5563 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5565 // Enchantment will not be applied if a different one already exists
5566 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5569 // Apply the temporary enchantment
5570 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
5571 item_owner
->ApplyEnchantment(item
, slot
, true);
5575 void Spell::EffectDisEnchant(uint32
/*i*/)
5577 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5580 Player
* p_caster
= (Player
*)m_caster
;
5581 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5584 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5586 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5588 // item will be removed at disenchanting end
5591 void Spell::EffectInebriate(uint32
/*i*/)
5593 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5596 Player
*player
= (Player
*)unitTarget
;
5597 uint16 currentDrunk
= player
->GetDrunkValue();
5598 uint16 drunkMod
= damage
* 256;
5599 if (currentDrunk
+ drunkMod
> 0xFFFF)
5600 currentDrunk
= 0xFFFF;
5602 currentDrunk
+= drunkMod
;
5603 player
->SetDrunkValue(currentDrunk
, m_CastItem
? m_CastItem
->GetEntry() : 0);
5606 void Spell::EffectFeedPet(uint32 i
)
5608 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5611 Player
*_player
= (Player
*)m_caster
;
5613 Item
* foodItem
= m_targets
.getItemTarget();
5617 Pet
*pet
= _player
->GetPet();
5624 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5629 _player
->DestroyItemCount(foodItem
,count
,true);
5630 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5632 m_caster
->CastCustomSpell(pet
, m_spellInfo
->EffectTriggerSpell
[i
], &benefit
, NULL
, NULL
, true);
5635 void Spell::EffectDismissPet(uint32
/*i*/)
5637 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5640 Pet
* pet
= m_caster
->GetPet();
5642 // not let dismiss dead pet
5643 if(!pet
||!pet
->isAlive())
5646 ((Player
*)m_caster
)->RemovePet(pet
, PET_SAVE_NOT_IN_SLOT
);
5649 void Spell::EffectSummonObject(uint32 i
)
5651 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5654 switch(m_spellInfo
->Effect
[i
])
5656 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5657 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5658 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5659 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5663 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5666 GameObject
* obj
= NULL
;
5668 obj
= m_caster
->GetMap()->GetGameObject(guid
);
5670 if(obj
) obj
->Delete();
5671 m_caster
->m_ObjectSlot
[slot
] = 0;
5674 GameObject
* pGameObj
= new GameObject
;
5677 // If dest location if present
5678 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5680 x
= m_targets
.m_destX
;
5681 y
= m_targets
.m_destY
;
5682 z
= m_targets
.m_destZ
;
5684 // Summon in random point all other units if location present
5686 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
5688 Map
*map
= m_caster
->GetMap();
5689 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5690 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
5696 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5697 int32 duration
= GetSpellDuration(m_spellInfo
);
5698 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5699 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5700 m_caster
->AddGameObject(pGameObj
);
5703 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5704 data
<< uint64(pGameObj
->GetGUID());
5705 m_caster
->SendMessageToSet(&data
, true);
5707 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5710 void Spell::EffectResurrect(uint32
/*effIndex*/)
5714 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5717 if(unitTarget
->isAlive())
5719 if(!unitTarget
->IsInWorld())
5722 switch (m_spellInfo
->Id
)
5724 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5726 if (roll_chance_i(67))
5728 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5732 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5734 if (roll_chance_i(50))
5736 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5744 Player
* pTarget
= ((Player
*)unitTarget
);
5746 if(pTarget
->isRessurectRequested()) // already have one active request
5749 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5750 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5752 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5753 SendResurrectRequest(pTarget
);
5756 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5758 if(!unitTarget
|| !unitTarget
->isAlive())
5761 if( unitTarget
->m_extraAttacks
)
5764 unitTarget
->m_extraAttacks
= damage
;
5767 void Spell::EffectParry(uint32
/*i*/)
5769 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5770 ((Player
*)unitTarget
)->SetCanParry(true);
5773 void Spell::EffectBlock(uint32
/*i*/)
5775 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5776 ((Player
*)unitTarget
)->SetCanBlock(true);
5779 void Spell::EffectMomentMove(uint32 i
)
5781 if(unitTarget
->isInFlight())
5784 if( m_spellInfo
->rangeIndex
== 1) //self range
5786 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5790 unitTarget
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
5792 unitTarget
->GetPosition(ox
, oy
, oz
);
5794 float fx2
, fy2
, fz2
; // getObjectHitPos overwrite last args in any result case
5795 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5800 unitTarget
->UpdateGroundPositionZ(fx
, fy
, fz
);
5803 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(), unitTarget
== m_caster
);
5807 void Spell::EffectReputation(uint32 i
)
5809 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5812 Player
*_player
= (Player
*)unitTarget
;
5814 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5816 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5818 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5823 _player
->GetReputationMgr().ModifyReputation(factionEntry
, rep_change
);
5826 void Spell::EffectQuestComplete(uint32 i
)
5828 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5831 Player
*_player
= (Player
*)m_caster
;
5833 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5834 _player
->AreaExploredOrEventHappens(quest_id
);
5837 void Spell::EffectSelfResurrect(uint32 i
)
5839 if(!unitTarget
|| unitTarget
->isAlive())
5841 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5843 if(!unitTarget
->IsInWorld())
5852 health
= uint32(-damage
);
5853 mana
= m_spellInfo
->EffectMiscValue
[i
];
5858 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5859 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5860 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5863 Player
*plr
= ((Player
*)unitTarget
);
5864 plr
->ResurrectPlayer(0.0f
);
5866 plr
->SetHealth( health
);
5867 plr
->SetPower(POWER_MANA
, mana
);
5868 plr
->SetPower(POWER_RAGE
, 0 );
5869 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5871 plr
->SpawnCorpseBones();
5876 void Spell::EffectSkinning(uint32
/*i*/)
5878 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5880 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5883 Creature
* creature
= (Creature
*) unitTarget
;
5884 int32 targetLevel
= creature
->getLevel();
5886 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5888 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5889 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5891 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5893 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5895 // Double chances for elites
5896 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5899 void Spell::EffectCharge(uint32
/*i*/)
5901 if(!unitTarget
|| !m_caster
)
5905 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5906 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5907 ((Creature
*)unitTarget
)->StopMoving();
5909 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5910 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5912 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5913 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5915 // not all charge effects used in negative spells
5916 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5917 m_caster
->Attack(unitTarget
,true);
5920 void Spell::EffectSummonCritter(uint32 i
)
5922 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5924 Player
* player
= (Player
*)m_caster
;
5926 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5930 Pet
* old_critter
= player
->GetMiniPet();
5932 // for same pet just despawn
5933 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5935 player
->RemoveMiniPet();
5939 // despawn old pet before summon new
5941 player
->RemoveMiniPet();
5944 Pet
* critter
= new Pet(MINI_PET
);
5946 Map
*map
= m_caster
->GetMap();
5947 uint32 pet_number
= objmgr
.GeneratePetNumber();
5948 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5949 pet_entry
, pet_number
))
5951 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5957 // If dest location if present
5958 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5960 x
= m_targets
.m_destX
;
5961 y
= m_targets
.m_destY
;
5962 z
= m_targets
.m_destZ
;
5964 // Summon if dest location not present near caster
5966 m_caster
->GetClosePoint(x
, y
, z
, critter
->GetObjectSize());
5968 critter
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5970 if(!critter
->IsPositionValid())
5972 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5973 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5978 critter
->SetOwnerGUID(m_caster
->GetGUID());
5979 critter
->SetCreatorGUID(m_caster
->GetGUID());
5980 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5981 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5983 critter
->AIM_Initialize();
5984 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5985 //critter->InitLevelupSpellsForLevel(); // none?
5986 critter
->SelectLevel(critter
->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
5987 critter
->SetUInt32Value(UNIT_NPC_FLAGS
, critter
->GetCreatureInfo()->npcflag
);
5988 // some mini-pets have quests
5990 // set timer for unsummon
5991 int32 duration
= GetSpellDuration(m_spellInfo
);
5993 critter
->SetDuration(duration
);
5995 std::string name
= player
->GetName();
5996 name
.append(petTypeSuffix
[critter
->getPetType()]);
5997 critter
->SetName( name
);
5998 player
->SetMiniPet(critter
);
6000 map
->Add((Creature
*)critter
);
6003 void Spell::EffectKnockBack(uint32 i
)
6005 if(!unitTarget
|| !m_caster
)
6008 // Effect only works on players
6009 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6012 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
6013 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
6015 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, 8+4+4+4+4+4);
6016 data
.append(unitTarget
->GetPackGUID());
6017 data
<< uint32(0); // Sequence
6018 data
<< float(vcos
); // x direction
6019 data
<< float(vsin
); // y direction
6020 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
6021 data
<< float(damage
/-10); // Z Movement speed (vertical)
6023 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6026 void Spell::EffectSendTaxi(uint32 i
)
6028 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6031 ((Player
*)unitTarget
)->ActivateTaxiPathTo(m_spellInfo
->EffectMiscValue
[i
],m_spellInfo
->Id
);
6034 void Spell::EffectPlayerPull(uint32 i
)
6036 if(!unitTarget
|| !m_caster
)
6039 // Effect only works on players
6040 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6043 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6044 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6046 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, 8+4+4+4+4+4);
6047 data
.append(unitTarget
->GetPackGUID());
6048 data
<< uint32(0); // Sequence
6049 data
<< float(vcos
); // x direction
6050 data
<< float(vsin
); // y direction
6052 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6053 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6055 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6058 void Spell::EffectDispelMechanic(uint32 i
)
6063 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6065 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6066 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6070 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6071 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6073 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6077 next
= Auras
.begin();
6083 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6085 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6087 Player
*_player
= (Player
*)m_caster
;
6088 Pet
*pet
= _player
->GetPet();
6095 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6096 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6097 pet
->setDeathState( ALIVE
);
6098 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6099 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6101 pet
->AIM_Initialize();
6103 _player
->PetSpellInitialize();
6104 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6107 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6110 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6112 if(!m_caster
->m_TotemSlot
[slot
])
6115 Creature
* totem
= m_caster
->GetMap()->GetCreature(m_caster
->m_TotemSlot
[slot
]);
6116 if(totem
&& totem
->isTotem())
6118 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6119 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6122 uint32 manacost
= m_caster
->GetCreateMana() * spellInfo
->ManaCostPercentage
/ 100;
6123 mana
+= manacost
* damage
/ 100;
6125 ((Totem
*)totem
)->UnSummon();
6130 m_caster
->CastCustomSpell(m_caster
, 39104, &mana
, NULL
, NULL
, true);
6133 void Spell::EffectDurabilityDamage(uint32 i
)
6135 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6138 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6140 // FIXME: some spells effects have value -1/-2
6141 // Possibly its mean -1 all player equipped items and -2 all items
6144 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
, (slot
< -1));
6148 // invalid slot value
6149 if(slot
>= INVENTORY_SLOT_BAG_END
)
6152 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6153 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
, damage
);
6156 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6158 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6161 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6163 // FIXME: some spells effects have value -1/-2
6164 // Possibly its mean -1 all player equipped items and -2 all items
6167 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
, (slot
< -1));
6171 // invalid slot value
6172 if(slot
>= INVENTORY_SLOT_BAG_END
)
6178 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6179 ((Player
*)unitTarget
)->DurabilityLoss(item
, double(damage
)/100.0f
);
6182 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6187 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6190 void Spell::EffectTransmitted(uint32 effIndex
)
6192 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6194 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6198 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6204 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6206 fx
= m_targets
.m_destX
;
6207 fy
= m_targets
.m_destY
;
6208 fz
= m_targets
.m_destZ
;
6210 //FIXME: this can be better check for most objects but still hack
6211 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6213 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6214 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6218 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6219 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6220 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6222 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6225 Map
*cMap
= m_caster
->GetMap();
6227 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6229 if ( !cMap
->IsInWater(fx
, fy
, fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6230 { // but this is not proper, we really need to ignore not materialized objects
6231 SendCastResult(SPELL_FAILED_NOT_HERE
);
6232 SendChannelUpdate(0);
6236 // replace by water level in this case
6237 fz
= cMap
->GetWaterLevel(fx
, fy
);
6239 // if gameobject is summoning object, it should be spawned right on caster's position
6240 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6242 m_caster
->GetPosition(fx
, fy
, fz
);
6245 GameObject
* pGameObj
= new GameObject
;
6247 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6248 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6254 int32 duration
= GetSpellDuration(m_spellInfo
);
6256 switch(goinfo
->type
)
6258 case GAMEOBJECT_TYPE_FISHINGNODE
:
6260 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6261 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6263 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6264 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6268 case 0: lastSec
= 3; break;
6269 case 1: lastSec
= 7; break;
6270 case 2: lastSec
= 13; break;
6271 case 3: lastSec
= 17; break;
6274 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6277 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6279 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
6281 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6282 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6286 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6287 case GAMEOBJECT_TYPE_CHEST
:
6294 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6296 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6298 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6299 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6301 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6302 //m_caster->AddGameObject(pGameObj);
6303 //m_ObjToDel.push_back(pGameObj);
6305 cMap
->Add(pGameObj
);
6307 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6308 data
<< uint64(pGameObj
->GetGUID());
6309 m_caster
->SendMessageToSet(&data
,true);
6311 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6313 GameObject
* linkedGO
= new GameObject
;
6314 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6315 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6317 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6318 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6319 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6320 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6322 linkedGO
->GetMap()->Add(linkedGO
);
6333 void Spell::EffectProspecting(uint32
/*i*/)
6335 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6338 Player
* p_caster
= (Player
*)m_caster
;
6339 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6342 if(itemTarget
->GetCount() < 5)
6345 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6347 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6348 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6349 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6352 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6355 void Spell::EffectMilling(uint32
/*i*/)
6357 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6360 Player
* p_caster
= (Player
*)m_caster
;
6361 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6364 if(itemTarget
->GetCount() < 5)
6367 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6369 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6370 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6371 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6374 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6377 void Spell::EffectSkill(uint32
/*i*/)
6379 sLog
.outDebug("WORLD: SkillEFFECT");
6382 void Spell::EffectSummonDemon(uint32 i
)
6384 // select center of summon position
6385 float center_x
= m_targets
.m_destX
;
6386 float center_y
= m_targets
.m_destY
;
6387 float center_z
= m_targets
.m_destZ
;
6389 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6391 int32 amount
= damage
> 0 ? damage
: 1;
6393 for(int32 count
= 0; count
< amount
; ++count
)
6396 // If dest location if present
6397 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6399 // Summon 1 unit in dest location
6402 px
= m_targets
.m_destX
;
6403 py
= m_targets
.m_destY
;
6404 pz
= m_targets
.m_destZ
;
6406 // Summon in random point all other units if location present
6408 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
6410 // Summon if dest location not present near caster
6412 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
6414 int32 duration
= GetSpellDuration(m_spellInfo
);
6416 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,duration
);
6417 if (!Charmed
) // something fatal, not attempt more
6420 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6421 Charmed
->SetLevel(m_caster
->getLevel());
6423 // TODO: Add damage/mana/hp according to level
6425 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6427 // Enslave demon effect, without mana cost and cooldown
6428 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6431 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6436 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6437 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6438 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6439 This is why we use a half sec delay between the visual effect and the resurrection itself */
6440 void Spell::EffectSpiritHeal(uint32
/*i*/)
6443 if(!unitTarget || unitTarget->isAlive())
6445 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6447 if(!unitTarget->IsInWorld())
6450 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6451 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6452 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6453 ((Player*)unitTarget)->SpawnCorpseBones();
6457 // remove insignia spell effect
6458 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6460 sLog
.outDebug("Effect: SkinPlayerCorpse");
6461 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6464 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6467 void Spell::EffectStealBeneficialBuff(uint32 i
)
6469 sLog
.outDebug("Effect: StealBeneficialBuff");
6471 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6474 std::vector
<Aura
*> steal_list
;
6475 // Create dispel mask by dispel type
6476 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6477 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6478 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6480 Aura
*aur
= (*itr
).second
;
6481 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6483 // Need check for passive? this
6484 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6485 steal_list
.push_back(aur
);
6488 // Ok if exist some buffs for dispel try dispel it
6489 if (!steal_list
.empty())
6491 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6492 int32 list_size
= steal_list
.size();
6493 // Dispell N = damage buffs (or while exist buffs for dispel)
6494 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6496 // Random select buff for dispel
6497 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6498 // Not use chance for steal
6499 // TODO possible need do it
6500 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6502 // Remove buff from list for prevent doubles
6503 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6506 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6508 j
= steal_list
.erase(j
);
6515 // Really try steal and send log
6516 if (!success_list
.empty())
6518 int32 count
= success_list
.size();
6519 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6520 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6521 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6522 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6523 data
<< uint8(0); // not used
6524 data
<< uint32(count
); // count
6525 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6527 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6528 data
<< uint32(spellInfo
->Id
); // Spell Id
6529 data
<< uint8(0); // 0 - steals !=0 transfers
6530 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6532 m_caster
->SendMessageToSet(&data
, true);
6537 void Spell::EffectKillCredit(uint32 i
)
6539 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6542 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6545 void Spell::EffectQuestFail(uint32 i
)
6547 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6550 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6553 void Spell::EffectActivateRune(uint32 eff_idx
)
6555 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6558 Player
*plr
= (Player
*)m_caster
;
6560 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6563 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6565 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6567 plr
->SetRuneCooldown(j
, 0);
6572 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6574 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6575 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6578 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6580 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6581 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6584 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);