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::EffectLeapForward
, // 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::EffectCreateRandomItem
, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
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::EffectPlayMusic
, //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::EffectLeapBack
, //138 SPELL_EFFECT_LEAP_BACK Leap back
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::EffectCharge2
, //149 SPELL_EFFECT_CHARGE2 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 item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL
, //160 SPELL_EFFECT_160 unused
221 &Spell::EffectNULL
, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectNULL
, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(uint32
/*i*/)
227 sLog
.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(uint32
/*i*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(uint32 i
)
237 if(!unitTarget
|| unitTarget
->isAlive())
240 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
243 if(!unitTarget
->IsInWorld())
246 Player
* pTarget
= ((Player
*)unitTarget
);
248 if(pTarget
->isRessurectRequested()) // already have one active request
251 uint32 health
= damage
;
252 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
253 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
254 SendResurrectRequest(pTarget
);
257 void Spell::EffectInstaKill(uint32
/*i*/)
259 if( !unitTarget
|| !unitTarget
->isAlive() )
263 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
265 uint32 entry
= unitTarget
->GetEntry();
269 case 416: spellID
=18789; break; //imp
270 case 417: spellID
=18792; break; //fellhunter
271 case 1860: spellID
=18790; break; //void
272 case 1863: spellID
=18791; break; //succubus
273 case 17252: spellID
=35701; break; //fellguard
275 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry
);
279 m_caster
->CastSpell(m_caster
, spellID
, true);
282 if(m_caster
== unitTarget
) // prevent interrupt message
285 m_caster
->DealDamage(unitTarget
, unitTarget
->GetHealth(), NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
288 void Spell::EffectEnvirinmentalDMG(uint32 i
)
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage
= m_spellInfo
->CalculateSimpleValue(i
);
298 m_caster
->CalcAbsorbResist(m_caster
, GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
300 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
301 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
302 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
, damage
);
305 void Spell::EffectSchoolDMG(uint32 effect_idx
)
307 if( unitTarget
&& unitTarget
->isAlive())
309 switch(m_spellInfo
->SpellFamilyName
)
311 case SPELLFAMILY_GENERIC
:
313 switch(m_spellInfo
->Id
) // better way to check unknown
315 // Meteor like spells (divided damage to targets)
316 case 24340: case 26558: case 28884: // Meteor
317 case 36837: case 38903: case 41276: // Meteor
318 case 26789: // Shard of the Fallen Star
319 case 31436: // Malevolent Cleave
320 case 35181: // Dive Bomb
321 case 40810: case 43267: case 43268: // Saber Lash
322 case 42384: // Brutal Swipe
323 case 45150: // Meteor Slash
324 case 64422: case 64688: // Sonic Screech
327 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
328 if(ihit
->effectMask
& (1<<effect_idx
))
331 damage
/= count
; // divide to all targets
334 // percent from health with min
335 case 25599: // Thundercrash
337 damage
= unitTarget
->GetHealth() / 2;
342 // Intercept (warrior spell trigger)
346 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
351 damage
= unitTarget
->GetMaxHealth() / 2;
357 case SPELLFAMILY_MAGE
:
360 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000))
362 m_caster
->CastSpell(m_caster
, 36032, true);
366 case SPELLFAMILY_WARRIOR
:
369 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x40000000000))
371 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
374 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000020000000000)) && m_spellInfo
->Category
==1209)
375 damage
+= int32(m_caster
->GetShieldBlockValue());
377 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x10000000000))
379 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
380 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
382 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
383 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000400))
384 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
385 // Heroic Throw ${$m1+$AP*.50}
386 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000100000000))
387 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
388 // Shockwave ${$m3/100*$AP}
389 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000800000000000))
391 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
393 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
397 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000080))
399 damage
+=int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 12 / 100);
403 case SPELLFAMILY_WARLOCK
:
405 // Incinerate Rank 1 & 2
406 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00004000000000)) && m_spellInfo
->SpellIconID
==2128)
408 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
409 // Check aura state for speed but aura state set not only for Immolate spell
410 if(unitTarget
->HasAuraState(AURA_STATE_CONFLAGRATE
))
412 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
413 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
416 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
417 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x00000000000004)))
426 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0001000000000000))
429 switch(m_spellInfo
->Id
)
431 case 47897: m_caster
->CastSpell(unitTarget
, 47960, true); break;
432 case 61290: m_caster
->CastSpell(unitTarget
, 61291, true); break;
434 sLog
.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo
->Id
);
438 // Conflagrate - consumes Immolate or Shadowflame
439 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_CONFLAGRATE
)
441 Aura
const* aura
= NULL
; // found req. aura for damage calculation
443 Unit::AuraList
const &mPeriodic
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
444 for(Unit::AuraList::const_iterator i
= mPeriodic
.begin(); i
!= mPeriodic
.end(); ++i
)
446 // for caster applied auras only
447 if ((*i
)->GetSpellProto()->SpellFamilyName
!= SPELLFAMILY_WARLOCK
||
448 (*i
)->GetCasterGUID()!=m_caster
->GetGUID())
452 if ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000004))
454 aura
= *i
; // it selected always if exist
459 if ((*i
)->GetSpellProto()->SpellFamilyFlags2
& 0x00000002)
460 aura
= *i
; // remember but wait possible Immolate as primary priority
463 // found Immolate or Shadowflame
466 int32 damagetick
= m_caster
->SpellDamageBonus(unitTarget
, aura
->GetSpellProto(), aura
->GetModifier()->m_amount
, DOT
);
467 damage
+= damagetick
* 4;
469 // Glyph of Conflagrate
470 if (!m_caster
->HasAura(56235))
471 unitTarget
->RemoveAurasByCasterSpell(aura
->GetId(), m_caster
->GetGUID());
477 case SPELLFAMILY_PRIEST
:
479 // Shadow Word: Death - deals damage equal to damage done to caster
480 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000200000000))
481 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
484 case SPELLFAMILY_DRUID
:
487 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000800000)) && m_spellInfo
->SpellVisual
[0]==6587)
489 // converts each extra point of energy into ($f1+$AP/410) additional damage
490 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
491 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
492 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
493 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
494 m_caster
->SetPower(POWER_ENERGY
,0);
497 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000001000) && m_spellInfo
->Effect
[2]==SPELL_EFFECT_ADD_COMBO_POINTS
)
500 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
503 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
505 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
509 case SPELLFAMILY_ROGUE
:
512 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)))
514 // consume from stack dozes not more that have combo-points
515 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
518 // Lookup for Deadly poison (only attacker applied)
519 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
520 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
521 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
522 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x10000)) &&
523 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
528 // count consumed deadly poison doses at target
531 uint32 spellId
= poison
->GetId();
532 uint32 doses
= poison
->GetStackAmount();
535 for (int i
=0; i
< doses
; i
++)
536 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
538 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
540 // Eviscerate and Envenom Bonus Damage (item set effect)
541 if(m_caster
->GetDummyAura(37169))
542 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
546 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00020000)) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
548 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
550 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
551 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
553 // Eviscerate and Envenom Bonus Damage (item set effect)
554 if(m_caster
->GetDummyAura(37169))
559 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000008))
561 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.21f
);
564 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
566 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
569 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000010000000))
571 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
575 case SPELLFAMILY_HUNTER
:
578 if (m_spellInfo
->SpellIconID
== 1578)
580 if (m_caster
->HasAura(57627)) // Charge 6 sec post-affect
584 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000000002)) && m_spellInfo
->SpellVisual
[0]==342)
586 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
589 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0008000000000000))
591 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
594 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000800)) && m_spellInfo
->maxLevel
> 0)
596 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
599 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
601 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
602 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
604 // Explosive Trap Effect
605 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000004))
607 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
611 case SPELLFAMILY_PALADIN
:
613 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
614 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)) && m_spellInfo
->SpellIconID
==2292)
616 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
617 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
618 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
619 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
620 // Get stack of Holy Vengeance on the target added by caster
622 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
623 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
624 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
626 stacks
= (*itr
)->GetStackAmount();
629 // + 10% for each application of Holy Vengeance on the target
631 damage
+= damage
* stacks
* 10 /100;
633 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
634 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
636 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
637 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
638 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
639 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
641 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
642 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000008000000000))
644 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
645 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
646 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
647 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
649 // Hammer of the Righteous
650 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000))
652 // Add main hand dps * effect[2] amount
653 float average
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
654 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
655 damage
+= count
* int32(average
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
657 // Shield of Righteousness
658 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
660 damage
+=int32(m_caster
->GetShieldBlockValue());
671 void Spell::EffectDummy(uint32 i
)
673 if (!unitTarget
&& !gameObjTarget
&& !itemTarget
)
676 // selection by spell family
677 switch(m_spellInfo
->SpellFamilyName
)
679 case SPELLFAMILY_GENERIC
:
681 switch(m_spellInfo
->Id
)
683 case 8063: // Deviate Fish
685 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
691 case 1: spell_id
= 8064; break; // Sleepy
692 case 2: spell_id
= 8065; break; // Invigorate
693 case 3: spell_id
= 8066; break; // Shrink
694 case 4: spell_id
= 8067; break; // Party Time!
695 case 5: spell_id
= 8068; break; // Healthy Spirit
697 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
700 case 8213: // Savory Deviate Delight
702 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
709 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
711 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
713 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
716 case 8593: // Symbol of life (restore creature to life)
717 case 31225: // Shimmering Vessel (restore creature to life)
719 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
721 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
724 case 12162: // Deep wounds
725 case 12850: // (now good common check for this spells)
732 // DW should benefit of attack power, damage percent mods etc.
733 // TODO: check if using offhand damage is correct and if it should be divided by 2
734 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
735 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
737 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
739 switch (m_spellInfo
->Id
)
741 case 12162: damage
*= 0.16f
; break; // Rank 1
742 case 12850: damage
*= 0.32f
; break; // Rank 2
743 case 12868: damage
*= 0.48f
; break; // Rank 3
745 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
749 // get remaining damage of old Deep Wound aura
750 Aura
* deepWound
= unitTarget
->GetAura(12721, 0);
753 int32 remainingTicks
= deepWound
->GetAuraDuration() / deepWound
->GetModifier()->periodictime
;
754 damage
+= remainingTicks
* deepWound
->GetModifier()->m_amount
;
757 // 1 tick/sec * 6 sec = 6 ticks
758 int32 deepWoundsDotBasePoints0
= int32(damage
/ 6);
759 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
762 case 13120: // net-o-matic
769 uint32 roll
= urand(0, 99);
771 if (roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
773 else if (roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
778 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
781 case 13567: // Dummy Trigger
783 // can be used for different aura triggering, so select by aura
784 if (!m_triggeredByAuraSpell
|| !unitTarget
)
787 switch(m_triggeredByAuraSpell
->Id
)
789 case 26467: // Persistent Shield
790 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
793 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
798 case 15998: // Capture Worg Pup
799 case 29435: // Capture Female Kaliri Hatchling
801 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
804 Creature
* creatureTarget
= (Creature
*)unitTarget
;
806 creatureTarget
->ForcedDespawn();
809 case 16589: // Noggenfogger Elixir
811 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
817 case 1: spell_id
= 16595; break;
818 case 2: spell_id
= 16593; break;
819 default:spell_id
= 16591; break;
822 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
825 case 17251: // Spirit Healer Res
827 if (!unitTarget
|| !m_originalCaster
)
830 if (m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
832 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
833 data
<< uint64(unitTarget
->GetGUID());
834 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
838 case 17271: // Test Fetid Skull
840 if (!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
843 uint32 spell_id
= roll_chance_i(50)
844 ? 17269 // Create Resonating Skull
845 : 17270; // Create Bone Dust
847 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
850 case 20577: // Cannibalize
852 m_caster
->CastSpell(m_caster
, 20578, false, NULL
);
854 case 23019: // Crystal Prison Dummy DND
856 if (!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
859 Creature
* creatureTarget
= (Creature
*)unitTarget
;
860 if (creatureTarget
->isPet())
863 GameObject
* pGameObj
= new GameObject
;
865 Map
*map
= creatureTarget
->GetMap();
867 // create before death for get proper coordinates
868 if (!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
869 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
870 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
) )
876 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
877 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
878 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
879 pGameObj
->SetSpellId(m_spellInfo
->Id
);
881 creatureTarget
->ForcedDespawn();
883 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
886 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
887 data
<< uint64(pGameObj
->GetGUID());
888 m_caster
->SendMessageToSet(&data
, true);
892 case 23074: // Arcanite Dragonling
895 m_caster
->CastSpell(m_caster
, 19804, true, m_CastItem
);
897 case 23075: // Mithril Mechanical Dragonling
900 m_caster
->CastSpell(m_caster
, 12749, true, m_CastItem
);
902 case 23076: // Mechanical Dragonling
905 m_caster
->CastSpell(m_caster
, 4073, true, m_CastItem
);
907 case 23133: // Gnomish Battle Chicken
910 m_caster
->CastSpell(m_caster
, 13166, true, m_CastItem
);
912 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
914 int32 r
= irand(0, 119);
915 if (r
< 20) // Transporter Malfunction - 1/6 polymorph
916 m_caster
->CastSpell(m_caster
, 23444, true);
917 else if (r
< 100) // Evil Twin - 4/6 evil twin
918 m_caster
->CastSpell(m_caster
, 23445, true);
919 else // Transporter Malfunction - 1/6 miss the target
920 m_caster
->CastSpell(m_caster
, 36902, true);
923 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
924 if (roll_chance_i(50)) // Gadgetzan Transporter - success
925 m_caster
->CastSpell(m_caster
, 23441, true);
926 else // Gadgetzan Transporter Failure - failure
927 m_caster
->CastSpell(m_caster
, 23446, true);
929 case 23645: // Hourglass Sand
930 m_caster
->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
932 case 23725: // Gift of Life (warrior bwl trinket)
933 m_caster
->CastSpell(m_caster
, 23782, true);
934 m_caster
->CastSpell(m_caster
, 23783, true);
936 case 25860: // Reindeer Transformation
938 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
941 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
942 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
944 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
946 //5 different spells used depending on mounted speed and if mount can fly or not
947 if (flyspeed
>= 4.1f
)
949 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
950 else if (flyspeed
>= 3.8f
)
952 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
953 else if (flyspeed
>= 1.6f
)
955 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
956 else if (speed
>= 2.0f
)
958 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
961 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
965 case 26074: // Holiday Cheer
966 // implemented at client side
968 case 28006: // Arcane Cloaking
970 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
971 // Naxxramas Entry Flag Effect DND
972 m_caster
->CastSpell(unitTarget
, 29294, true);
975 case 29200: // Purify Helboar Meat
977 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
980 uint32 spell_id
= roll_chance_i(50)
981 ? 29277 // Summon Purified Helboar Meat
982 : 29278; // Summon Toxic Helboar Meat
984 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
987 case 29858: // Soulshatter
988 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
989 m_caster
->CastSpell(unitTarget
,32835,true);
991 case 30458: // Nigh Invulnerability
994 if (roll_chance_i(86)) // Nigh-Invulnerability - success
995 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
996 else // Complete Vulnerability - backfire in 14% casts
997 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
999 case 30507: // Poultryizer
1002 if (roll_chance_i(80)) // Poultryized! - success
1003 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
1004 else // Poultryized! - backfire 20%
1005 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
1007 case 33060: // Make a Wish
1009 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1012 uint32 spell_id
= 0;
1016 case 1: spell_id
= 33053; break; // Mr Pinchy's Blessing
1017 case 2: spell_id
= 33057; break; // Summon Mighty Mr. Pinchy
1018 case 3: spell_id
= 33059; break; // Summon Furious Mr. Pinchy
1019 case 4: spell_id
= 33062; break; // Tiny Magical Crawdad
1020 case 5: spell_id
= 33064; break; // Mr. Pinchy's Gift
1023 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
1026 case 35745: // Socrethar's Stone
1029 switch(m_caster
->GetAreaId())
1031 case 3900: spell_id
= 35743; break; // Socrethar Portal
1032 case 3742: spell_id
= 35744; break; // Socrethar Portal
1036 m_caster
->CastSpell(m_caster
, spell_id
, true);
1039 case 37674: // Chaos Blast
1044 int32 basepoints0
= 100;
1045 m_caster
->CastCustomSpell(unitTarget
, 37675, &basepoints0
, NULL
, NULL
, true);
1048 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1050 // selecting one from Bloodstained Fortune item
1052 switch(urand(1, 20))
1054 case 1: newitemid
= 32688; break;
1055 case 2: newitemid
= 32689; break;
1056 case 3: newitemid
= 32690; break;
1057 case 4: newitemid
= 32691; break;
1058 case 5: newitemid
= 32692; break;
1059 case 6: newitemid
= 32693; break;
1060 case 7: newitemid
= 32700; break;
1061 case 8: newitemid
= 32701; break;
1062 case 9: newitemid
= 32702; break;
1063 case 10: newitemid
= 32703; break;
1064 case 11: newitemid
= 32704; break;
1065 case 12: newitemid
= 32705; break;
1066 case 13: newitemid
= 32706; break;
1067 case 14: newitemid
= 32707; break;
1068 case 15: newitemid
= 32708; break;
1069 case 16: newitemid
= 32709; break;
1070 case 17: newitemid
= 32710; break;
1071 case 18: newitemid
= 32711; break;
1072 case 19: newitemid
= 32712; break;
1073 case 20: newitemid
= 32713; break;
1078 DoCreateItem(i
, newitemid
);
1081 // Demon Broiled Surprise
1082 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1085 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1088 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1092 case 44875: // Complete Raptor Capture
1094 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1097 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1099 creatureTarget
->ForcedDespawn();
1101 //cast spell Raptor Capture Credit
1102 m_caster
->CastSpell(m_caster
, 42337, true, NULL
);
1105 case 34665: //Administer Antidote
1107 if (!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1109 // Spell has scriptable target but for sure.
1110 if (unitTarget
->GetTypeId() != TYPEID_UNIT
)
1113 uint32 health
= unitTarget
->GetHealth();
1116 unitTarget
->GetPosition(x
, y
, z
);
1117 o
= unitTarget
->GetOrientation();
1118 ((Creature
*)unitTarget
)->ForcedDespawn();
1120 if (Creature
* summon
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000))
1122 summon
->SetHealth(health
);
1123 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992, summon
);
1126 summon
->AI()->AttackStart(m_caster
);
1130 case 44997: // Converting Sentry
1132 //Converted Sentry Credit
1133 m_caster
->CastSpell(m_caster
, 45009, true);
1136 case 45030: // Impale Emissary
1138 // Emissary of Hate Credit
1139 m_caster
->CastSpell(m_caster
, 45088, true);
1142 case 55004: // Nitro Boosts
1145 if (roll_chance_i(95)) // Nitro Boosts - success
1146 m_caster
->CastSpell(m_caster
, 54861, true, m_CastItem
);
1147 else // Knocked Up - backfire 5%
1148 m_caster
->CastSpell(m_caster
, 46014, true, m_CastItem
);
1150 case 50243: // Teach Language
1152 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1155 // spell has a 1/3 chance to trigger one of the below
1156 if (roll_chance_i(66))
1158 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1160 // 1000001 - gnomish binary
1161 m_caster
->CastSpell(m_caster
, 50242, true);
1165 // 01001000 - goblin binary
1166 m_caster
->CastSpell(m_caster
, 50246, true);
1171 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1173 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1176 if (BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1177 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1179 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1182 case 51592: // Pickup Primordial Hatchling
1184 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1187 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1189 creatureTarget
->ForcedDespawn();
1193 case 52308: // Take Sputum Sample
1199 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1200 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1202 if (m_caster
->HasAura(reqAuraID
,0))
1203 m_caster
->CastSpell(m_caster
, spellID
, true, NULL
);
1207 return; // additional data for dummy[0]
1211 case 52759: // Ancestral Awakening
1214 m_caster
->CastCustomSpell(unitTarget
, 52752, &damage
, NULL
, NULL
, true);
1216 case 53341: // Rune of Cinderglacier
1217 case 53343: // Rune of Razorice
1219 // Runeforging Credit
1220 m_caster
->CastSpell(m_caster
, 54586, true);
1223 case 58418: // Portal to Orgrimmar
1224 case 58420: // Portal to Stormwind
1225 return; // implemented in EffectScript[0]
1226 case 59640: // Underbelly Elixir
1228 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1231 uint32 spell_id
= 0;
1234 case 1: spell_id
= 59645; break;
1235 case 2: spell_id
= 59831; break;
1236 case 3: spell_id
= 59843; break;
1238 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
1241 case 60932: // Disengage (one from creature versions)
1244 m_caster
->CastSpell(unitTarget
,60934,true,NULL
);
1248 //All IconID Check in there
1249 switch(m_spellInfo
->SpellIconID
)
1251 // Berserking (troll racial traits)
1254 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1255 int32 melee_mod
= 10;
1256 if (healthPerc
<= 40)
1258 if (healthPerc
< 100 && healthPerc
> 40)
1259 melee_mod
= 10+(100-healthPerc
)/3;
1261 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1262 int32 hasteModBasePoints1
= (5-melee_mod
);
1263 int32 hasteModBasePoints2
= 5;
1265 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1266 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1267 m_caster
->CastCustomSpell(m_caster
, 26635, &hasteModBasePoints0
, &hasteModBasePoints1
, &hasteModBasePoints2
, true, NULL
);
1273 case SPELLFAMILY_MAGE
:
1274 switch(m_spellInfo
->Id
)
1276 case 11958: // Cold Snap
1278 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1281 // immediately finishes the cooldown on Frost spells
1282 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1283 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1285 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1287 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1288 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1289 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0)
1291 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
, true);
1298 case 32826: // Polymorph Cast Visual
1300 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1302 //Polymorph Cast Visual Rank 1
1303 const uint32 spell_list
[6] = {
1304 32813, // Squirrel Form
1305 32816, // Giraffe Form
1306 32817, // Serpent Form
1307 32818, // Dragonhawk Form
1308 32819, // Worgen Form
1311 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1317 case SPELLFAMILY_WARRIOR
:
1319 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x1)) && m_spellInfo
->SpellVisual
[0] == 867)
1321 int32 chargeBasePoints0
= damage
;
1322 m_caster
->CastCustomSpell(m_caster
, 34846, &chargeBasePoints0
, NULL
, NULL
, true);
1326 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000))
1331 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1332 // Glyph of Execution bonus
1333 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1334 rage
+=aura
->GetModifier()->m_amount
;
1336 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1337 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1338 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1339 m_caster
->SetPower(POWER_RAGE
, 0);
1343 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000200000))
1347 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1352 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000))
1354 m_damage
+= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
1357 switch(m_spellInfo
->Id
)
1364 m_caster
->CastSpell(unitTarget
, 21887, true);// spell mod
1370 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1371 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1377 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1382 case SPELLFAMILY_WARLOCK
:
1384 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000040000))
1386 // In 303 exist spirit depend
1387 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1388 switch (m_spellInfo
->Id
)
1390 case 1454: damage
+=spirit
; break;
1391 case 1455: damage
+=spirit
*15/10; break;
1392 case 1456: damage
+=spirit
*2; break;
1393 case 11687: damage
+=spirit
*25/10; break;
1397 case 57946: damage
+=spirit
*3; break;
1399 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1402 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1403 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1404 if (unitTarget
&& (int32(unitTarget
->GetHealth()) > damage
))
1406 // Shouldn't Appear in Combat Log
1407 unitTarget
->ModifyHealth(-damage
);
1409 int32 mana
= damage
;
1410 // Improved Life Tap mod
1411 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1412 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1414 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1415 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1417 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1420 int32 manaFeedVal
= 0;
1421 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1422 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1424 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1425 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1427 if (manaFeedVal
> 0)
1429 manaFeedVal
= manaFeedVal
* mana
/ 100;
1430 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1434 SendCastResult(SPELL_FAILED_FIZZLE
);
1438 case SPELLFAMILY_PRIEST
:
1440 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0080000000000000))
1447 switch(m_spellInfo
->Id
)
1449 case 47540: hurt
= 47758; heal
= 47757; break;
1450 case 53005: hurt
= 53001; heal
= 52986; break;
1451 case 53006: hurt
= 53002; heal
= 52987; break;
1452 case 53007: hurt
= 53003; heal
= 52988; break;
1454 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1457 if (m_caster
->IsFriendlyTo(unitTarget
))
1458 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1460 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1464 case SPELLFAMILY_DRUID
:
1466 if (m_spellInfo
->SpellFamilyFlags2
& UI64LIT(0x00000100))
1468 //Shapeshifting into an animal form or mounting cancels the effect.
1469 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1471 if(m_triggeredByAuraSpell
)
1472 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1476 //Any effect which causes you to lose control of your character will supress the starfall effect.
1477 if (m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1480 switch(m_spellInfo
->Id
)
1482 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1483 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1484 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1485 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1487 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1492 case SPELLFAMILY_ROGUE
:
1493 switch(m_spellInfo
->Id
)
1497 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1500 Player
*pCaster
= ((Player
*)m_caster
);
1502 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1506 // all poison enchantments is temporary
1507 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1511 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1515 for (int s
=0;s
<3;s
++)
1517 if (pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1520 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1521 if (!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1524 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1527 m_caster
->CastSpell(unitTarget
, 5940, true);
1530 case 14185: // Preparation
1532 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1535 //immediately finishes the cooldown on certain Rogue abilities
1536 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1537 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1539 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1541 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000024000000860)))
1542 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
1548 case 31231: // Cheat Death
1550 m_caster
->CastSpell(m_caster
, 45182, true);
1555 case SPELLFAMILY_HUNTER
:
1557 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
1559 if (!unitTarget
|| !unitTarget
->isAlive())
1564 // check dazed affect
1565 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1566 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1568 if ((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1581 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000400000000000))
1583 Unit
* target
= unitTarget
;
1585 switch(m_spellInfo
->Id
)
1587 case 781: // player case
1591 case 57635: spellid
= 57636; break; // one from creature cases
1592 case 61507: spellid
= 61508; break; // one from creature cases
1594 sLog
.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo
->Id
);
1597 if (!target
|| !target
->isAlive())
1599 m_caster
->CastSpell(target
,spellid
,true,NULL
);
1602 switch(m_spellInfo
->Id
)
1604 case 23989: // Readiness talent
1606 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1609 //immediately finishes the cooldown for hunter abilities
1610 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1611 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1613 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1615 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1616 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
1622 case 37506: // Scatter Shot
1624 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1627 // break Auto Shot and autohit
1628 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1629 m_caster
->AttackStop();
1630 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1635 case SPELLFAMILY_PALADIN
:
1636 switch(m_spellInfo
->SpellIconID
)
1638 case 156: // Holy Shock
1646 switch(m_spellInfo
->Id
)
1648 case 20473: hurt
= 25912; heal
= 25914; break;
1649 case 20929: hurt
= 25911; heal
= 25913; break;
1650 case 20930: hurt
= 25902; heal
= 25903; break;
1651 case 27174: hurt
= 27176; heal
= 27175; break;
1652 case 33072: hurt
= 33073; heal
= 33074; break;
1653 case 48824: hurt
= 48822; heal
= 48820; break;
1654 case 48825: hurt
= 48823; heal
= 48821; break;
1656 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1660 if (m_caster
->IsFriendlyTo(unitTarget
))
1661 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1663 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1667 case 561: // Judgement of command
1672 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1673 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1677 if (!unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1679 // decreased damage (/2) for non-stunned target.
1680 SpellModifier
*mod
= new SpellModifier
;
1681 mod
->op
= SPELLMOD_DAMAGE
;
1683 mod
->type
= SPELLMOD_PCT
;
1684 mod
->spellId
= m_spellInfo
->Id
;
1685 mod
->mask
= UI64LIT(0x0000020000000000);
1686 mod
->mask2
= UI64LIT(0x0);
1688 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1689 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
1691 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1694 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
1700 switch(m_spellInfo
->Id
)
1702 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1707 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1710 case 31789: // Righteous Defense (step 1)
1712 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1714 // non-standard cast requirement check
1715 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1717 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
1718 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
,true);
1719 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1723 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1724 // Clear targets for eff 1
1725 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1726 ihit
->effectMask
&= ~(1<<1);
1728 // not empty (checked)
1729 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1731 // chance to be selected from list
1732 float chance
= 100.0f
/attackers
.size();
1734 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1736 if (!roll_chance_f(chance
))
1739 AddUnitTarget((*aItr
), 1);
1742 // now let next effect cast spell at each target.
1745 case 37877: // Blessing of Faith
1750 uint32 spell_id
= 0;
1751 switch(unitTarget
->getClass())
1753 case CLASS_DRUID
: spell_id
= 37878; break;
1754 case CLASS_PALADIN
: spell_id
= 37879; break;
1755 case CLASS_PRIEST
: spell_id
= 37880; break;
1756 case CLASS_SHAMAN
: spell_id
= 37881; break;
1757 default: return; // ignore for not healing classes
1760 m_caster
->CastSpell(m_caster
, spell_id
, true);
1765 case SPELLFAMILY_SHAMAN
:
1767 if (m_spellInfo
->SpellFamilyFlags
& 0x400000)
1769 // TODO: use expect spell for enchant (if exist talent)
1770 // In 3.0.3 no mods present for rockbiter
1771 uint32 spell_id
= 0;
1772 switch(m_spellInfo
->Id
)
1774 case 8017: spell_id
= 36494; break; // Rank 1
1775 case 8018: spell_id
= 36750; break; // Rank 2
1776 case 8019: spell_id
= 36755; break; // Rank 3
1777 case 10399: spell_id
= 36759; break; // Rank 4
1779 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo
->Id
);
1783 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spell_id
);
1787 sLog
.outError("WORLD: unknown spell id %i", spell_id
);
1791 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1794 for(int j
= BASE_ATTACK
; j
<= OFF_ATTACK
; ++j
)
1796 if (Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(j
)))
1798 if (item
->IsFitToSpellRequirements(m_spellInfo
))
1800 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1802 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1803 // at calculation applied affect from Elemental Weapons talent
1804 // real enchantment damage-1
1805 spell
->m_currentBasePoints
[1] = damage
-1;
1807 SpellCastTargets targets
;
1808 targets
.setItemTarget( item
);
1809 spell
->prepare(&targets
);
1816 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000)) && m_spellInfo
->SpellIconID
==1673)
1818 m_caster
->CastSpell(unitTarget
, 52025, true);
1821 // Healing Stream Totem
1822 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
1824 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1827 // Mana Spring Totem
1828 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
1830 if (unitTarget
->getPowerType()!=POWER_MANA
)
1832 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1835 if (m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1837 if (!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1839 // Glyph of Mana Tide
1840 if (Unit
*owner
= m_caster
->GetOwner())
1841 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1842 damage
+=dummy
->GetModifier()->m_amount
;
1843 // Regenerate 6% of Total Mana Every 3 secs
1844 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1845 m_caster
->CastCustomSpell(unitTarget
, 39609, &EffectBasePoints0
, NULL
, NULL
, true, NULL
, NULL
, m_originalCasterGUID
);
1849 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1851 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1853 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1856 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1857 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1858 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1860 if ((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1861 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000200000)) &&
1862 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1864 m_damage
+= m_damage
* damage
/ 100;
1872 case SPELLFAMILY_DEATHKNIGHT
:
1874 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x002000))
1876 if (m_caster
->IsFriendlyTo(unitTarget
))
1878 if (unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1881 int32 bp
= damage
* 1.5f
;
1882 m_caster
->CastCustomSpell(unitTarget
, 47633, &bp
, NULL
, NULL
, true);
1887 m_caster
->CastCustomSpell(unitTarget
, 47632, &bp
, NULL
, NULL
, true);
1892 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000100000000000))
1894 m_caster
->CastSpell(m_caster
, 51209, true);
1898 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000010))
1901 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
1902 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
1904 if (itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
1905 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
1906 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
1915 int32 bp
= count
* m_caster
->GetMaxHealth() * m_spellInfo
->DmgMultiplier
[0] / 100;
1916 m_caster
->CastCustomSpell(m_caster
, 45470, &bp
, NULL
, NULL
, true);
1923 if (PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
, i
))
1925 m_caster
->AddPetAura(petSpell
);
1929 // Script based implementation. Must be used only for not good for implementation in core spell effects
1930 // So called only for not proccessed cases
1932 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
1933 else if (unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
1934 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
1935 else if (itemTarget
)
1936 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
1939 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1941 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1944 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1948 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1953 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1956 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1958 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1959 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1963 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1969 m_caster
->CastSpell(unitTarget
,spellInfo
,false);
1972 void Spell::EffectForceCast(uint32 i
)
1977 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1980 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1984 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1988 unitTarget
->CastSpell(unitTarget
, spellInfo
, true, NULL
, NULL
, m_originalCasterGUID
);
1991 void Spell::EffectTriggerSpell(uint32 effIndex
)
1993 // only unit case known
1996 if(gameObjTarget
|| itemTarget
)
1997 sLog
.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo
->Id
);
2001 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effIndex
];
2004 switch(triggered_spell_id
)
2006 // Vanish (not exist)
2009 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
2010 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
2011 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
2013 // if this spell is given to NPC it must handle rest by it's own AI
2014 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2017 // get highest rank of the Stealth spell
2019 const PlayerSpellMap
& sp_list
= ((Player
*)unitTarget
)->GetSpellMap();
2020 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
2022 // only highest rank is shown in spell book, so simply check if shown in spell book
2023 if (!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
2026 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2030 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
2032 spellId
= spellInfo
->Id
;
2037 // no Stealth spell found
2041 // reset cooldown on it if needed
2042 if (((Player
*)unitTarget
)->HasSpellCooldown(spellId
))
2043 ((Player
*)unitTarget
)->RemoveSpellCooldown(spellId
);
2045 m_caster
->CastSpell(unitTarget
, spellId
, true);
2049 case 23770: // Sayge's Dark Fortune of *
2050 // not exist, common cooldown can be implemented in scripts if need.
2052 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2056 SpellEntry
const* spell
= sSpellStore
.LookupEntry(24575);
2060 for (int j
=0; j
< spell
->StackAmount
; ++j
)
2061 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2064 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2068 SpellEntry
const* spell
= sSpellStore
.LookupEntry(26464);
2072 for (int j
=0; j
< spell
->StackAmount
; ++j
)
2073 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2076 // Righteous Defense
2079 m_caster
->CastSpell(unitTarget
, 31790, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2085 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2086 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
2088 // remove all harmful spells on you...
2089 if( // ignore positive and passive auras
2090 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
2091 // ignore physical auras
2092 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
2094 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
2095 iter
= Auras
.begin();
2100 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2103 if (Unit
*pet
= unitTarget
->GetPet())
2104 pet
->CastSpell(pet
, 28305, true);
2110 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2113 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2117 // select formal caster for triggered spell
2118 Unit
* caster
= m_caster
;
2120 // some triggered spells require specific equipment
2121 if (spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
2123 // main hand weapon required
2124 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
2126 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
2128 // skip spell if no weapon in slot or broken
2129 if (!item
|| item
->IsBroken() )
2132 // skip spell if weapon not fit to triggered spell
2133 if (!item
->IsFitToSpellRequirements(spellInfo
))
2137 // offhand hand weapon required
2138 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
2140 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
2142 // skip spell if no weapon in slot or broken
2143 if (!item
|| item
->IsBroken() )
2146 // skip spell if weapon not fit to triggered spell
2147 if (!item
->IsFitToSpellRequirements(spellInfo
))
2153 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2154 // so this just for speedup places in else
2155 caster
= IsSpellWithCasterSourceTargetsOnly(spellInfo
) ? unitTarget
: m_caster
;
2158 caster
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
2161 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2163 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2166 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2170 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2171 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2176 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2178 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2181 void Spell::EffectJump(uint32 i
)
2183 if(m_caster
->isInFlight())
2186 // Init dest coordinates
2188 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2190 x
= m_targets
.m_destX
;
2191 y
= m_targets
.m_destY
;
2192 z
= m_targets
.m_destZ
;
2194 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2196 // explicit cast data from client or server-side cast
2197 // some spell at client send caster
2198 Unit
* pTarget
= NULL
;
2199 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2200 pTarget
= m_targets
.getUnitTarget();
2201 else if(unitTarget
->getVictim())
2202 pTarget
= m_caster
->getVictim();
2203 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2204 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2206 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2209 o
= m_caster
->GetOrientation();
2213 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2214 o
= m_caster
->GetOrientation();
2216 else if(gameObjTarget
)
2218 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2219 o
= m_caster
->GetOrientation();
2223 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2227 m_caster
->NearTeleportTo(x
, y
, z
, o
, true);
2230 void Spell::EffectTeleportUnits(uint32 i
)
2232 if(!unitTarget
|| unitTarget
->isInFlight())
2235 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2237 case TARGET_INNKEEPER_COORDINATES
:
2239 // Only players can teleport to innkeeper
2240 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2243 ((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);
2246 case TARGET_AREAEFFECT_INSTANT
: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2247 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2249 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2252 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2256 if(st
->target_mapId
==unitTarget
->GetMapId())
2257 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2258 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2259 ((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);
2262 case TARGET_BEHIND_VICTIM
:
2264 Unit
*pTarget
= NULL
;
2266 // explicit cast data from client or server-side cast
2267 // some spell at client send caster
2268 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2269 pTarget
= m_targets
.getUnitTarget();
2270 else if(unitTarget
->getVictim())
2271 pTarget
= unitTarget
->getVictim();
2272 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2273 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2275 // Init dest coordinates
2276 float x
= m_targets
.m_destX
;
2277 float y
= m_targets
.m_destY
;
2278 float z
= m_targets
.m_destZ
;
2279 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2280 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2285 // If not exist data for dest location - return
2286 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2288 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2291 // Init dest coordinates
2292 float x
= m_targets
.m_destX
;
2293 float y
= m_targets
.m_destY
;
2294 float z
= m_targets
.m_destZ
;
2295 float orientation
= unitTarget
->GetOrientation();
2297 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2302 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2303 switch ( m_spellInfo
->Id
)
2305 // Dimensional Ripper - Everlook
2308 int32 r
= irand(0, 119);
2309 if ( r
>= 70 ) // 7/12 success
2311 if ( r
< 100 ) // 4/12 evil twin
2312 m_caster
->CastSpell(m_caster
, 23445, true);
2314 m_caster
->CastSpell(m_caster
, 23449, true);
2318 // Ultrasafe Transporter: Toshley's Station
2321 if ( roll_chance_i(50) ) // 50% success
2323 int32 rand_eff
= urand(1, 7);
2327 // soul split - evil
2328 m_caster
->CastSpell(m_caster
, 36900, true);
2331 // soul split - good
2332 m_caster
->CastSpell(m_caster
, 36901, true);
2335 // Increase the size
2336 m_caster
->CastSpell(m_caster
, 36895, true);
2339 // Decrease the size
2340 m_caster
->CastSpell(m_caster
, 36893, true);
2345 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2346 m_caster
->CastSpell(m_caster
, 36897, true);
2348 m_caster
->CastSpell(m_caster
, 36899, true);
2353 m_caster
->CastSpell(m_caster
, 36940, true);
2357 m_caster
->CastSpell(m_caster
, 23445, true);
2363 // Dimensional Ripper - Area 52
2366 if ( roll_chance_i(50) ) // 50% success
2368 int32 rand_eff
= urand(1, 4);
2372 // soul split - evil
2373 m_caster
->CastSpell(m_caster
, 36900, true);
2376 // soul split - good
2377 m_caster
->CastSpell(m_caster
, 36901, true);
2380 // Increase the size
2381 m_caster
->CastSpell(m_caster
, 36895, true);
2386 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2387 m_caster
->CastSpell(m_caster
, 36897, true);
2389 m_caster
->CastSpell(m_caster
, 36899, true);
2399 void Spell::EffectApplyAura(uint32 i
)
2404 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2405 if( !unitTarget
->isAlive() && !IsDeathPersistentSpell(m_spellInfo
) &&
2406 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2409 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2413 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2415 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2417 // Now Reduce spell duration using data received at spell hit
2418 int32 duration
= Aur
->GetAuraMaxDuration();
2419 int32 limitduration
= GetDiminishingReturnsLimitDuration(m_diminishGroup
,m_spellInfo
);
2420 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
, duration
, m_caster
, m_diminishLevel
,limitduration
);
2421 Aur
->setDiminishGroup(m_diminishGroup
);
2423 // if Aura removed and deleted, do not continue.
2424 if(duration
== 0 && !(Aur
->IsPermanent()))
2430 if(duration
!= Aur
->GetAuraMaxDuration())
2432 Aur
->SetAuraMaxDuration(duration
);
2433 Aur
->SetAuraDuration(duration
);
2436 unitTarget
->AddAura(Aur
);
2439 void Spell::EffectUnlearnSpecialization( uint32 i
)
2441 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2444 Player
*_player
= (Player
*)unitTarget
;
2445 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2447 _player
->removeSpell(spellToUnlearn
);
2449 sLog
.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2452 void Spell::EffectPowerDrain(uint32 i
)
2454 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2457 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2461 if(!unitTarget
->isAlive())
2463 if(unitTarget
->getPowerType() != drain_power
)
2468 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2470 //add spell damage bonus
2471 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2473 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2474 uint32 power
= damage
;
2475 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2476 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2479 if(curPower
< power
)
2480 new_damage
= curPower
;
2484 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2486 // Don`t restore from self drain
2487 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2489 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2490 if(manaMultiplier
==0)
2493 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2494 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2496 int32 gain
= int32(new_damage
* manaMultiplier
);
2498 m_caster
->EnergizeBySpell(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
2502 void Spell::EffectSendEvent(uint32 EffectIndex
)
2505 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2507 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2508 m_caster
->GetMap()->ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2511 void Spell::EffectPowerBurn(uint32 i
)
2513 if (m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2516 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2520 if (!unitTarget
->isAlive())
2522 if (unitTarget
->getPowerType()!=powertype
)
2527 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2528 if (m_spellInfo
->ManaCostPercentage
)
2530 uint32 maxdamage
= m_caster
->GetMaxPower(powertype
) * damage
* 2 / 100;
2531 damage
= unitTarget
->GetMaxPower(powertype
) * damage
/ 100;
2532 if(damage
> maxdamage
) damage
= maxdamage
;
2535 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2537 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2538 uint32 power
= damage
;
2539 if (powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2540 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2542 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2544 unitTarget
->ModifyPower(powertype
, -new_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 new_damage
= int32(new_damage
* multiplier
);
2551 m_damage
+= new_damage
;
2554 void Spell::EffectHeal( uint32
/*i*/ )
2556 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2558 // Try to get original caster
2559 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2561 // Skip if m_originalCaster not available
2565 int32 addhealth
= damage
;
2567 // Vessel of the Naaru (Vial of the Sunwell trinket)
2568 if (m_spellInfo
->Id
== 45064)
2570 // Amount of heal - depends from stacked Holy Energy
2571 int damageAmount
= 0;
2572 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2573 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
2574 if ((*i
)->GetId() == 45062)
2575 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2577 m_caster
->RemoveAurasDueToSpell(45062);
2579 addhealth
+= damageAmount
;
2581 // Swiftmend - consumes Regrowth or Rejuvenation
2582 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2584 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2585 // find most short by duration
2586 Aura
*targetAura
= NULL
;
2587 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2589 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
&&
2590 // Regrowth or Rejuvenation 0x40 | 0x10
2591 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000050)))
2593 if (!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2600 sLog
.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUIDLow(), unitTarget
->GetTypeId());
2606 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2611 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2612 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2614 // Glyph of Swiftmend
2615 if (!caster
->HasAura(54824))
2616 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2618 addhealth
+= tickheal
* tickcount
;
2621 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2623 m_healing
+=addhealth
;
2627 void Spell::EffectHealPct( uint32
/*i*/ )
2629 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2631 // Try to get original caster
2632 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2634 // Skip if m_originalCaster not available
2638 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2639 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
2640 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DAMAGE
, addhealth
, this);
2642 int32 gain
= caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2643 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2647 void Spell::EffectHealMechanical( uint32
/*i*/ )
2649 // Mechanic creature type should be correctly checked by targetCreatureType field
2650 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2652 // Try to get original caster
2653 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2655 // Skip if m_originalCaster not available
2659 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2660 caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2664 void Spell::EffectHealthLeech(uint32 i
)
2668 if (!unitTarget
->isAlive())
2674 sLog
.outDebug("HealthLeech :%i", damage
);
2676 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2678 if (Player
*modOwner
= m_caster
->GetSpellModOwner())
2679 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2681 int32 new_damage
= int32(damage
*multiplier
);
2682 uint32 curHealth
= unitTarget
->GetHealth();
2683 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
);
2684 if (curHealth
< new_damage
)
2685 new_damage
= curHealth
;
2687 if (m_caster
->isAlive())
2689 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2690 m_caster
->DealHeal(m_caster
, uint32(new_damage
), m_spellInfo
);
2694 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2696 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2699 Player
* player
= (Player
*)unitTarget
;
2701 uint32 newitemid
= itemtype
;
2702 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2705 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2709 // bg reward have some special in code work
2711 switch(m_spellInfo
->Id
)
2713 case SPELL_AV_MARK_WINNER
:
2714 case SPELL_AV_MARK_LOSER
:
2715 bgType
= BATTLEGROUND_AV
;
2717 case SPELL_WS_MARK_WINNER
:
2718 case SPELL_WS_MARK_LOSER
:
2719 bgType
= BATTLEGROUND_WS
;
2721 case SPELL_AB_MARK_WINNER
:
2722 case SPELL_AB_MARK_LOSER
:
2723 bgType
= BATTLEGROUND_AB
;
2731 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2732 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2734 int32 basePoints
= m_currentBasePoints
[i
];
2735 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2737 num_to_add
= basePoints
+ irand(1, randomPoints
);
2739 num_to_add
= basePoints
+ 1;
2741 else if (pProto
->MaxCount
== 1)
2743 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2745 int32 basePoints
= m_currentBasePoints
[i
];
2746 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2747 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2754 if (num_to_add
> pProto
->GetMaxStackSize())
2755 num_to_add
= pProto
->GetMaxStackSize();
2757 // init items_count to 1, since 1 item will be created regardless of specialization
2759 // the chance to create additional items
2760 float additionalCreateChance
=0.0f
;
2761 // the maximum number of created additional items
2762 uint8 additionalMaxNum
=0;
2763 // get the chance and maximum number for creating extra items
2764 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2766 // roll with this chance till we roll not to create or we create the max num
2767 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2771 // really will be created more items
2772 num_to_add
*= items_count
;
2774 // can the player store the new item?
2775 ItemPosCountVec dest
;
2776 uint32 no_space
= 0;
2777 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2778 if( msg
!= EQUIP_ERR_OK
)
2780 // convert to possible store amount
2781 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2782 num_to_add
-= no_space
;
2785 // if not created by another reason from full inventory or unique items amount limitation
2786 player
->SendEquipError( msg
, NULL
, NULL
);
2793 // create the new item and store it
2794 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2796 // was it successful? return error if not
2799 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2803 // set the "Crafted by ..." property of the item
2804 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2805 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
, player
->GetGUIDLow());
2807 // send info to the client
2809 player
->SendNewItem(pItem
, num_to_add
, true, bgType
== 0);
2811 // we succeeded in creating at least one item, so a levelup is possible
2813 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2816 // for battleground marks send by mail if not add all expected
2817 if(no_space
> 0 && bgType
)
2819 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BattleGroundTypeId(bgType
)))
2820 bg
->SendRewardMarkByMail(player
, newitemid
, no_space
);
2824 void Spell::EffectCreateItem(uint32 i
)
2826 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2829 void Spell::EffectCreateItem2(uint32 i
)
2831 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2833 Player
* player
= (Player
*)m_caster
;
2835 uint32 item_id
= m_spellInfo
->EffectItemType
[i
];
2837 DoCreateItem(i
, item_id
);
2839 // special case: fake item replaced by generate using spell_loot_template
2840 if (IsLootCraftingSpell(m_spellInfo
))
2842 if (!player
->HasItemCount(item_id
, 1))
2847 player
->DestroyItemCount(item_id
, count
, true);
2849 // create some random items
2850 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
2854 void Spell::EffectCreateRandomItem(uint32 i
)
2856 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2858 Player
* player
= (Player
*)m_caster
;
2860 // create some random items
2861 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
2864 void Spell::EffectPersistentAA(uint32 i
)
2866 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2868 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
2869 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2871 int32 duration
= GetSpellDuration(m_spellInfo
);
2872 DynamicObject
* dynObj
= new DynamicObject
;
2873 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
))
2878 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2879 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2880 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2881 m_caster
->AddDynObject(dynObj
);
2882 m_caster
->GetMap()->Add(dynObj
);
2885 void Spell::EffectEnergize(uint32 i
)
2889 if(!unitTarget
->isAlive())
2892 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2895 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2897 // Some level depends spells
2898 int level_multiplier
= 0;
2900 switch (m_spellInfo
->Id
)
2902 case 9512: // Restore Energy
2903 level_diff
= m_caster
->getLevel() - 40;
2904 level_multiplier
= 2;
2906 case 24571: // Blood Fury
2907 level_diff
= m_caster
->getLevel() - 60;
2908 level_multiplier
= 10;
2910 case 24532: // Burst of Energy
2911 level_diff
= m_caster
->getLevel() - 60;
2912 level_multiplier
= 4;
2914 case 31930: // Judgements of the Wise
2915 case 63375: // Improved Stormstrike
2916 damage
= damage
* unitTarget
->GetCreateMana() / 100;
2922 damage
-= level_multiplier
* level_diff
;
2927 if(unitTarget
->GetMaxPower(power
) == 0)
2930 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2932 // Mad Alchemist's Potion
2933 if (m_spellInfo
->Id
== 45051)
2935 // find elixirs on target
2936 uint32 elixir_mask
= 0;
2937 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2938 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2940 uint32 spell_id
= itr
->second
->GetId();
2941 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2942 elixir_mask
|= mask
;
2945 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2946 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2948 // get all available elixirs by mask and spell level
2949 std::vector
<uint32
> elixirs
;
2950 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2951 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2953 if (itr
->second
& elixir_mask
)
2955 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2958 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2959 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2962 elixirs
.push_back(itr
->first
);
2966 if (!elixirs
.empty())
2968 // cast random elixir on target
2969 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2970 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2975 void Spell::EffectEnergisePct(uint32 i
)
2979 if (!unitTarget
->isAlive())
2982 if (m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2985 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2987 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2991 uint32 gain
= damage
* maxPower
/ 100;
2992 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2995 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2997 Player
* player
= (Player
*)m_caster
;
3003 if (Script
->GOHello(player
, gameObjTarget
))
3006 switch (gameObjTarget
->GetGoType())
3008 case GAMEOBJECT_TYPE_DOOR
:
3009 case GAMEOBJECT_TYPE_BUTTON
:
3010 gameObjTarget
->UseDoorOrButton();
3011 player
->GetMap()->ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
3014 case GAMEOBJECT_TYPE_QUESTGIVER
:
3015 // start or end quest
3016 player
->PrepareQuestMenu(guid
);
3017 player
->SendPreparedQuest(guid
);
3020 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
3021 // triggering linked GO
3022 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
3023 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3026 case GAMEOBJECT_TYPE_GOOBER
:
3027 // goober_scripts can be triggered if the player don't have the quest
3028 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
3030 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
3031 player
->GetMap()->ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
3034 // cast goober spell
3035 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
3036 ///Quest require to be active for GO using
3037 if (player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
3040 gameObjTarget
->AddUniqueUse(player
);
3041 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
3043 //TODO? Objective counting called without spell check but with quest objective check
3044 // if send spell id then this line will duplicate to spell casting call (double counting)
3045 // So we or have this line and not required in quest_template have reqSpellIdN
3046 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3047 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
3049 // triggering linked GO
3050 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
3051 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3055 case GAMEOBJECT_TYPE_CHEST
:
3056 // TODO: possible must be moved to loot release (in different from linked triggering)
3057 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
3059 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
3060 player
->GetMap()->ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
3063 // triggering linked GO
3064 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
3065 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3067 // Don't return, let loots been taken
3074 player
->SendLoot(guid
, loottype
);
3077 void Spell::EffectOpenLock(uint32 effIndex
)
3079 if (!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
3081 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
3085 Player
* player
= (Player
*)m_caster
;
3093 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
3094 // Arathi Basin banner opening !
3095 if (goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
3096 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
3098 //CanUseBattleGroundObject() already called in CheckCast()
3099 // in battleground check
3100 if (BattleGround
*bg
= player
->GetBattleGround())
3102 // check if it's correct bg
3103 if (bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
3104 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3108 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
3110 //CanUseBattleGroundObject() already called in CheckCast()
3111 // in battleground check
3112 if (BattleGround
*bg
= player
->GetBattleGround())
3114 if (bg
->GetTypeID() == BATTLEGROUND_EY
)
3115 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3119 lockId
= goInfo
->GetLockId();
3120 guid
= gameObjTarget
->GetGUID();
3122 else if (itemTarget
)
3124 lockId
= itemTarget
->GetProto()->LockID
;
3125 guid
= itemTarget
->GetGUID();
3129 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3133 SkillType skillId
= SKILL_NONE
;
3134 int32 reqSkillValue
= 0;
3137 SpellCastResult res
= CanOpenLock(effIndex
, lockId
, skillId
, reqSkillValue
, skillValue
);
3138 if (res
!= SPELL_CAST_OK
)
3140 SendCastResult(res
);
3144 SendLoot(guid
, LOOT_SKINNING
);
3146 // not allow use skill grow at item base open
3147 if (!m_CastItem
&& skillId
!= SKILL_NONE
)
3149 // update skill if really known
3150 if (uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3154 // Allow one skill-up until respawned
3155 if (!gameObjTarget
->IsInSkillupList(player
->GetGUIDLow()) &&
3156 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
))
3157 gameObjTarget
->AddToSkillupList(player
->GetGUIDLow());
3159 else if (itemTarget
)
3162 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3168 void Spell::EffectSummonChangeItem(uint32 i
)
3170 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3173 Player
*player
= (Player
*)m_caster
;
3175 // applied only to using item
3179 // ... only to item in own inventory/bank/equip_slot
3180 if (m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3183 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3187 uint16 pos
= m_CastItem
->GetPos();
3189 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3193 for(uint8 j
= PERM_ENCHANTMENT_SLOT
; j
<=TEMP_ENCHANTMENT_SLOT
; ++j
)
3195 if (m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)))
3196 pNewItem
->SetEnchantment(EnchantmentSlot(j
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(j
)));
3199 if (m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3201 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3202 player
->DurabilityLoss(pNewItem
, loosePercent
);
3205 if (player
->IsInventoryPos(pos
))
3207 ItemPosCountVec dest
;
3208 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3209 if (msg
== EQUIP_ERR_OK
)
3211 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3213 // prevent crash at access and unexpected charges counting with item update queue corrupt
3214 if (m_CastItem
==m_targets
.getItemTarget())
3215 m_targets
.setItemTarget(NULL
);
3219 player
->StoreItem( dest
, pNewItem
, true);
3223 else if (player
->IsBankPos (pos
))
3225 ItemPosCountVec dest
;
3226 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3227 if (msg
== EQUIP_ERR_OK
)
3229 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3231 // prevent crash at access and unexpected charges counting with item update queue corrupt
3232 if (m_CastItem
==m_targets
.getItemTarget())
3233 m_targets
.setItemTarget(NULL
);
3237 player
->BankItem( dest
, pNewItem
, true);
3241 else if (player
->IsEquipmentPos (pos
))
3244 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3245 if (msg
== EQUIP_ERR_OK
)
3247 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3249 // prevent crash at access and unexpected charges counting with item update queue corrupt
3250 if (m_CastItem
==m_targets
.getItemTarget())
3251 m_targets
.setItemTarget(NULL
);
3255 player
->EquipItem( dest
, pNewItem
, true);
3256 player
->AutoUnequipOffhandIfNeed();
3265 void Spell::EffectProficiency(uint32
/*i*/)
3267 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3269 Player
*p_target
= (Player
*)unitTarget
;
3271 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3272 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_WEAPON
&& !(p_target
->GetWeaponProficiency() & subClassMask
))
3274 p_target
->AddWeaponProficiency(subClassMask
);
3275 p_target
->SendProficiency(ITEM_CLASS_WEAPON
, p_target
->GetWeaponProficiency());
3277 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_ARMOR
&& !(p_target
->GetArmorProficiency() & subClassMask
))
3279 p_target
->AddArmorProficiency(subClassMask
);
3280 p_target
->SendProficiency(ITEM_CLASS_ARMOR
, p_target
->GetArmorProficiency());
3284 void Spell::EffectApplyAreaAura(uint32 i
)
3288 if (!unitTarget
->isAlive())
3291 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3292 unitTarget
->AddAura(Aur
);
3295 void Spell::EffectSummonType(uint32 i
)
3297 switch(m_spellInfo
->EffectMiscValueB
[i
])
3299 case SUMMON_TYPE_GUARDIAN
:
3300 case SUMMON_TYPE_POSESSED
:
3301 case SUMMON_TYPE_POSESSED2
:
3302 case SUMMON_TYPE_FORCE_OF_NATURE
:
3303 case SUMMON_TYPE_GUARDIAN2
:
3304 case SUMMON_TYPE_GUARDIAN3
:
3305 // Jewelery statue case (totem like)
3306 if(m_spellInfo
->SpellIconID
== 2056)
3307 EffectSummonTotem(i
);
3309 EffectSummonGuardian(i
);
3311 case SUMMON_TYPE_WILD
:
3312 EffectSummonWild(i
);
3314 case SUMMON_TYPE_DEMON
:
3315 case SUMMON_TYPE_INFERNO
:
3316 EffectSummonDemon(i
);
3318 case SUMMON_TYPE_SUMMON
:
3319 case SUMMON_TYPE_ELEMENTAL
:
3322 case SUMMON_TYPE_CRITTER
:
3323 case SUMMON_TYPE_CRITTER2
:
3324 case SUMMON_TYPE_CRITTER3
:
3325 EffectSummonCritter(i
);
3327 case SUMMON_TYPE_TOTEM_SLOT1
:
3328 case SUMMON_TYPE_TOTEM_SLOT2
:
3329 case SUMMON_TYPE_TOTEM_SLOT3
:
3330 case SUMMON_TYPE_TOTEM_SLOT4
:
3331 case SUMMON_TYPE_TOTEM
:
3332 EffectSummonTotem(i
);
3334 case SUMMON_TYPE_UNKNOWN1
:
3335 case SUMMON_TYPE_UNKNOWN2
:
3336 case SUMMON_TYPE_UNKNOWN3
:
3337 case SUMMON_TYPE_UNKNOWN4
:
3338 case SUMMON_TYPE_UNKNOWN5
:
3341 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3346 void Spell::EffectSummon(uint32 i
)
3348 if (m_caster
->GetPetGUID())
3353 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3356 uint32 level
= m_caster
->getLevel();
3357 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3359 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3361 // Summon in dest location
3363 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3365 x
= m_targets
.m_destX
;
3366 y
= m_targets
.m_destY
;
3367 z
= m_targets
.m_destZ
;
3368 spawnCreature
->Relocate(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, -m_caster
->GetOrientation());
3371 // set timer for unsummon
3372 int32 duration
= GetSpellDuration(m_spellInfo
);
3374 spawnCreature
->SetDuration(duration
);
3379 Map
*map
= m_caster
->GetMap();
3380 uint32 pet_number
= objmgr
.GeneratePetNumber();
3381 if (!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
3382 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3384 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3385 delete spawnCreature
;
3389 // Summon in dest location
3391 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3393 x
= m_targets
.m_destX
;
3394 y
= m_targets
.m_destY
;
3395 z
= m_targets
.m_destZ
;
3398 m_caster
->GetClosePoint(x
, y
, z
, spawnCreature
->GetObjectSize());
3400 spawnCreature
->Relocate(x
, y
, z
, -m_caster
->GetOrientation());
3402 if (!spawnCreature
->IsPositionValid())
3404 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3405 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3406 delete spawnCreature
;
3410 // set timer for unsummon
3411 int32 duration
= GetSpellDuration(m_spellInfo
);
3413 spawnCreature
->SetDuration(duration
);
3415 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3416 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
3417 spawnCreature
->setPowerType(POWER_MANA
);
3418 spawnCreature
->setFaction(m_caster
->getFaction());
3419 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3420 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3421 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3422 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3423 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3424 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3425 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3426 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3428 spawnCreature
->InitStatsForLevel(level
, m_caster
);
3430 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3432 spawnCreature
->AIM_Initialize();
3433 spawnCreature
->InitPetCreateSpells();
3434 spawnCreature
->InitLevelupSpellsForLevel();
3435 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3436 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3438 std::string name
= m_caster
->GetName();
3439 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3440 spawnCreature
->SetName( name
);
3442 map
->Add((Creature
*)spawnCreature
);
3444 m_caster
->SetPet(spawnCreature
);
3446 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3448 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3449 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3450 ((Player
*)m_caster
)->PetSpellInitialize();
3454 void Spell::EffectLearnSpell(uint32 i
)
3459 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3461 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3462 EffectLearnPetSpell(i
);
3467 Player
*player
= (Player
*)unitTarget
;
3469 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3470 player
->learnSpell(spellToLearn
,false);
3472 sLog
.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3475 void Spell::EffectDispel(uint32 i
)
3480 // Fill possible dispell list
3481 std::vector
<Aura
*> dispel_list
;
3483 // Create dispel mask by dispel type
3484 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3485 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3486 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3487 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3489 Aura
*aur
= (*itr
).second
;
3490 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3492 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3494 bool positive
= true;
3495 if (!aur
->IsPositive())
3498 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3500 // do not remove positive auras if friendly target
3501 // negative auras if non-friendly target
3502 if (positive
== unitTarget
->IsFriendlyTo(m_caster
))
3505 // Add aura to dispel list
3506 dispel_list
.push_back(aur
);
3509 // Ok if exist some buffs for dispel try dispel it
3510 if (!dispel_list
.empty())
3512 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3513 std::list
< uint32
> fail_list
; // spell_id
3514 int32 list_size
= dispel_list
.size();
3515 // Dispell N = damage buffs (or while exist buffs for dispel)
3516 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3518 // Random select buff for dispel
3519 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3521 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3522 // Base dispel chance
3523 // TODO: possible chance depend from spell level??
3524 int32 miss_chance
= 0;
3525 // Apply dispel mod from aura caster
3526 if (Unit
*caster
= aur
->GetCaster())
3528 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3529 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3532 if (roll_chance_i(miss_chance
))
3533 fail_list
.push_back(aur
->GetId());
3535 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3536 // Remove buff from list for prevent doubles
3537 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3539 Aura
*dispeled
= *j
;
3540 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3542 j
= dispel_list
.erase(j
);
3549 // Send success log and really remove auras
3550 if (!success_list
.empty())
3552 int32 count
= success_list
.size();
3553 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3554 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3555 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3556 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3557 data
<< uint8(0); // not used
3558 data
<< uint32(count
); // count
3559 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3561 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3562 data
<< uint32(spellInfo
->Id
); // Spell Id
3563 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3564 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3566 m_caster
->SendMessageToSet(&data
, true);
3568 // On success dispel
3570 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3572 int32 heal_amount
= m_spellInfo
->CalculateSimpleValue(1);
3573 m_caster
->CastCustomSpell(m_caster
, 19658, &heal_amount
, NULL
, NULL
, true);
3576 // Send fail log to client
3577 if (!fail_list
.empty())
3579 // Failed to dispell
3580 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3581 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3582 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3583 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3584 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3585 data
<< uint32(*j
); // Spell Id
3586 m_caster
->SendMessageToSet(&data
, true);
3591 void Spell::EffectDualWield(uint32
/*i*/)
3593 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3594 ((Player
*)unitTarget
)->SetCanDualWield(true);
3597 void Spell::EffectPull(uint32
/*i*/)
3599 // TODO: create a proper pull towards distract spell center for distract
3600 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3603 void Spell::EffectDistract(uint32
/*i*/)
3605 // Check for possible target
3606 if (!unitTarget
|| unitTarget
->isInCombat())
3609 // target must be OK to do this
3610 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3613 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3615 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3617 // For players just turn them
3619 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3620 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3621 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3625 // Set creature Distracted, Stop it, And turn it
3626 unitTarget
->SetOrientation(angle
);
3627 unitTarget
->StopMoving();
3628 unitTarget
->GetMotionMaster()->MoveDistract(damage
* IN_MILISECONDS
);
3632 void Spell::EffectPickPocket(uint32
/*i*/)
3634 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3637 // victim must be creature and attackable
3638 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
))
3641 // victim have to be alive and humanoid or undead
3642 if (unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3644 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3646 if (chance
> irand(0, 19))
3648 // Stealing successful
3649 //sLog.outDebug("Sending loot from pickpocket");
3650 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3654 // Reveal action + get attack
3655 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3656 if (((Creature
*)unitTarget
)->AI())
3657 ((Creature
*)unitTarget
)->AI()->AttackedBy(m_caster
);
3662 void Spell::EffectAddFarsight(uint32 i
)
3664 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3667 int32 duration
= GetSpellDuration(m_spellInfo
);
3668 DynamicObject
* dynObj
= new DynamicObject
;
3670 // set radius to 0: spell not expected to work as persistent aura
3671 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
, 0))
3676 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3677 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3678 m_caster
->AddDynObject(dynObj
);
3679 m_caster
->GetMap()->Add(dynObj
);
3680 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3683 void Spell::EffectSummonWild(uint32 i
)
3685 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3686 if (!creature_entry
)
3689 uint32 level
= m_caster
->getLevel();
3691 // level of creature summoned using engineering item based at engineering skill level
3692 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3694 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3695 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3697 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3705 // select center of summon position
3706 float center_x
= m_targets
.m_destX
;
3707 float center_y
= m_targets
.m_destY
;
3708 float center_z
= m_targets
.m_destZ
;
3710 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3712 int32 amount
= damage
> 0 ? damage
: 1;
3714 for(int32 count
= 0; count
< amount
; ++count
)
3717 // If dest location if present
3718 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3720 // Summon 1 unit in dest location
3723 px
= m_targets
.m_destX
;
3724 py
= m_targets
.m_destY
;
3725 pz
= m_targets
.m_destZ
;
3727 // Summon in random point all other units if location present
3729 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3731 // Summon if dest location not present near caster
3733 m_caster
->GetClosePoint(px
, py
, pz
, 3.0f
);
3735 int32 duration
= GetSpellDuration(m_spellInfo
);
3737 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3739 m_caster
->SummonCreature(creature_entry
, px
, py
, pz
, m_caster
->GetOrientation(), summonType
, duration
);
3743 void Spell::EffectSummonGuardian(uint32 i
)
3745 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3749 // set timer for unsummon
3750 int32 duration
= GetSpellDuration(m_spellInfo
);
3752 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3753 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3754 // so this code hack in fact
3755 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
) == 0))
3756 if(m_caster
->FindGuardianWithEntry(pet_entry
))
3757 return; // find old guardian, ignore summon
3759 // in another case summon new
3760 uint32 level
= m_caster
->getLevel();
3762 // level of pet summoned using engineering item based at engineering skill level
3763 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& m_CastItem
)
3765 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3766 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3768 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3771 level
= skill202
/ 5;
3776 // select center of summon position
3777 float center_x
= m_targets
.m_destX
;
3778 float center_y
= m_targets
.m_destY
;
3779 float center_z
= m_targets
.m_destZ
;
3781 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3783 int32 amount
= damage
> 0 ? damage
: 1;
3785 for(int32 count
= 0; count
< amount
; ++count
)
3787 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3789 Map
*map
= m_caster
->GetMap();
3790 uint32 pet_number
= objmgr
.GeneratePetNumber();
3791 if (!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3792 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3794 sLog
.outError("no such creature entry %u", m_spellInfo
->EffectMiscValue
[i
]);
3795 delete spawnCreature
;
3800 // If dest location if present
3801 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3803 // Summon 1 unit in dest location
3806 px
= m_targets
.m_destX
;
3807 py
= m_targets
.m_destY
;
3808 pz
= m_targets
.m_destZ
;
3810 // Summon in random point all other units if location present
3812 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3814 // Summon if dest location not present near caster
3816 m_caster
->GetClosePoint(px
, py
, pz
,spawnCreature
->GetObjectSize());
3818 spawnCreature
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
3820 if (!spawnCreature
->IsPositionValid())
3822 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3823 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3824 delete spawnCreature
;
3829 spawnCreature
->SetDuration(duration
);
3831 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3832 spawnCreature
->setPowerType(POWER_MANA
);
3833 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
3834 spawnCreature
->setFaction(m_caster
->getFaction());
3835 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3836 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3837 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3838 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3839 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3841 spawnCreature
->InitStatsForLevel(level
, m_caster
);
3842 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3844 spawnCreature
->AIM_Initialize();
3846 m_caster
->AddGuardian(spawnCreature
);
3848 map
->Add((Creature
*)spawnCreature
);
3852 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3857 if (unitTarget
->isInFlight())
3860 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3863 m_caster
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
3865 unitTarget
->NearTeleportTo(fx
, fy
, fz
, -m_caster
->GetOrientation(), unitTarget
==m_caster
);
3868 void Spell::EffectLearnSkill(uint32 i
)
3870 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3876 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3877 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3878 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
? skillval
: 1, damage
* 75);
3881 void Spell::EffectAddHonor(uint32
/*i*/)
3883 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3886 // not scale value for item based reward (/10 value expected)
3889 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/ 10);
3890 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());
3894 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3897 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
3898 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
3899 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
3903 //maybe we have correct honor_gain in damage already
3904 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3905 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3909 void Spell::EffectTradeSkill(uint32
/*i*/)
3911 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3913 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3914 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3915 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3918 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3920 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3925 Player
* p_caster
= (Player
*)m_caster
;
3927 // not grow at item use at item case
3928 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3930 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3934 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3938 // item can be in trade slot and have owner diff. from caster
3939 Player
* item_owner
= itemTarget
->GetOwner();
3943 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3945 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3946 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3947 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3948 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3951 // remove old enchanting before applying new if equipped
3952 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3954 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3956 // add new enchanting if equipped
3957 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3960 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3962 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3967 Player
* p_caster
= (Player
*)m_caster
;
3969 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3973 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3977 // support only enchantings with add socket in this slot
3979 bool add_socket
= false;
3980 for(int i
= 0; i
< 3; ++i
)
3982 if (pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3990 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.",
3991 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3996 // item can be in trade slot and have owner diff. from caster
3997 Player
* item_owner
= itemTarget
->GetOwner();
4001 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4003 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4004 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4005 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4006 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4009 // remove old enchanting before applying new if equipped
4010 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
4012 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
4014 // add new enchanting if equipped
4015 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
4018 void Spell::EffectEnchantItemTmp(uint32 i
)
4020 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4023 Player
* p_caster
= (Player
*)m_caster
;
4028 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
4030 // Shaman Rockbiter Weapon
4031 if (i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
4033 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
4035 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
4036 // with already applied percent bonus from Elemental Weapons talent
4037 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4038 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4039 switch(enchnting_damage
)
4042 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4044 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
4045 case 5: enchant_id
= 3025; break; // 20%
4047 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
4048 case 7: enchant_id
= 3027; break; // 20%
4050 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
4051 case 10: enchant_id
= 503; break; // 14%
4052 case 11: enchant_id
= 3031; break; // 20%
4054 case 15: enchant_id
= 3035; break; // 0%
4055 case 16: enchant_id
= 1663; break; // 7%
4056 case 17: enchant_id
= 3033; break; // 14%
4057 case 18: enchant_id
= 3034; break; // 20%
4059 case 28: enchant_id
= 3038; break; // 0%
4060 case 29: enchant_id
= 683; break; // 7%
4061 case 31: enchant_id
= 3036; break; // 14%
4062 case 33: enchant_id
= 3037; break; // 20%
4064 case 40: enchant_id
= 3041; break; // 0%
4065 case 42: enchant_id
= 1664; break; // 7%
4066 case 45: enchant_id
= 3039; break; // 14%
4067 case 48: enchant_id
= 3040; break; // 20%
4069 case 49: enchant_id
= 3044; break; // 0%
4070 case 52: enchant_id
= 2632; break; // 7%
4071 case 55: enchant_id
= 3042; break; // 14%
4072 case 58: enchant_id
= 3043; break; // 20%
4074 case 62: enchant_id
= 2633; break; // 0%
4075 case 66: enchant_id
= 3018; break; // 7%
4076 case 70: enchant_id
= 3019; break; // 14%
4077 case 74: enchant_id
= 3020; break; // 20%
4079 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
4086 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
4090 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4093 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
4097 // select enchantment duration
4100 // rogue family enchantments exception by duration
4101 if(m_spellInfo
->Id
== 38615)
4102 duration
= 1800; // 30 mins
4103 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4104 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
4105 duration
= 3600; // 1 hour
4106 // shaman family enchantments
4107 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
4108 duration
= 1800; // 30 mins
4109 // other cases with this SpellVisual already selected
4110 else if(m_spellInfo
->SpellVisual
[0] == 215)
4111 duration
= 1800; // 30 mins
4112 // some fishing pole bonuses
4113 else if(m_spellInfo
->SpellVisual
[0] == 563)
4114 duration
= 600; // 10 mins
4115 // shaman rockbiter enchantments
4116 else if(m_spellInfo
->SpellVisual
[0] == 0)
4117 duration
= 1800; // 30 mins
4118 else if(m_spellInfo
->Id
== 29702)
4119 duration
= 300; // 5 mins
4120 else if(m_spellInfo
->Id
== 37360)
4121 duration
= 300; // 5 mins
4124 duration
= 3600; // 1 hour
4126 // item can be in trade slot and have owner diff. from caster
4127 Player
* item_owner
= itemTarget
->GetOwner();
4131 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4133 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4134 p_caster
->GetName(), p_caster
->GetSession()->GetAccountId(),
4135 itemTarget
->GetProto()->Name1
, itemTarget
->GetEntry(),
4136 item_owner
->GetName(), item_owner
->GetSession()->GetAccountId());
4139 // remove old enchanting before applying new if equipped
4140 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
, false);
4142 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
* 1000, 0);
4144 // add new enchanting if equipped
4145 item_owner
->ApplyEnchantment(itemTarget
, TEMP_ENCHANTMENT_SLOT
, true);
4148 void Spell::EffectTameCreature(uint32
/*i*/)
4150 if(m_caster
->GetPetGUID())
4156 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4159 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4161 if(creatureTarget
->isPet())
4164 if(m_caster
->getClass() != CLASS_HUNTER
)
4167 // cast finish successfully
4168 //SendChannelUpdate(0);
4171 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4172 if(!pet
) // in versy specific state like near world end/etc.
4175 // "kill" original creature
4176 creatureTarget
->ForcedDespawn();
4178 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4180 // prepare visual effect for levelup
4181 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4184 pet
->GetMap()->Add((Creature
*)pet
);
4186 // visual effect for levelup
4187 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4189 // caster have pet now
4190 m_caster
->SetPet(pet
);
4192 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4194 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4195 ((Player
*)m_caster
)->PetSpellInitialize();
4199 void Spell::EffectSummonPet(uint32 i
)
4201 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4203 Pet
*OldSummon
= m_caster
->GetPet();
4205 // if pet requested type already exist
4208 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4210 // pet in corpse state can't be summoned
4211 if( OldSummon
->isDead() )
4214 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4217 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4219 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4220 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4222 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4224 ((Player
*)m_caster
)->PetSpellInitialize();
4229 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4230 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4235 Pet
* NewSummon
= new Pet
;
4237 // petentry==0 for hunter "call pet" (current pet summoned if any)
4238 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4240 if(NewSummon
->getPetType()==SUMMON_PET
)
4242 // Remove Demonic Sacrifice auras (known pet)
4243 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4244 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4246 if((*itr
)->GetModifier()->m_miscvalue
== 2228)
4248 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4249 itr
= auraClassScripts
.begin();
4259 // not error in case fail hunter call pet
4266 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4270 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4275 Map
*map
= m_caster
->GetMap();
4276 uint32 pet_number
= objmgr
.GeneratePetNumber();
4277 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4278 petentry
, pet_number
))
4285 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4287 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4289 if(!NewSummon
->IsPositionValid())
4291 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4292 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4297 uint32 petlevel
= m_caster
->getLevel();
4298 NewSummon
->setPetType(SUMMON_PET
);
4300 uint32 faction
= m_caster
->getFaction();
4301 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4303 if ( ((Creature
*)m_caster
)->isTotem() )
4304 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4306 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4309 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4310 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4311 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
4312 NewSummon
->setFaction(faction
);
4313 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4314 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4315 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4316 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4317 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4318 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4320 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4321 // this enables pet details window (Shift+P)
4323 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4324 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4325 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4327 if(m_caster
->IsPvP())
4328 NewSummon
->SetPvP(true);
4330 NewSummon
->InitStatsForLevel(petlevel
, m_caster
);
4331 NewSummon
->InitPetCreateSpells();
4332 NewSummon
->InitLevelupSpellsForLevel();
4333 NewSummon
->InitTalentForLevel();
4335 if(NewSummon
->getPetType()==SUMMON_PET
)
4337 // Remove Demonic Sacrifice auras (new pet)
4338 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4339 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4341 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4343 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4344 itr
= auraClassScripts
.begin();
4350 // generate new name for summon pet
4351 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4352 if(!new_name
.empty())
4353 NewSummon
->SetName(new_name
);
4355 else if(NewSummon
->getPetType()==HUNTER_PET
)
4356 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4358 NewSummon
->AIM_Initialize();
4359 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4360 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4362 map
->Add((Creature
*)NewSummon
);
4364 m_caster
->SetPet(NewSummon
);
4365 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4367 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4369 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4370 ((Player
*)m_caster
)->PetSpellInitialize();
4374 void Spell::EffectLearnPetSpell(uint32 i
)
4376 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4379 Player
*_player
= (Player
*)m_caster
;
4381 Pet
*pet
= _player
->GetPet();
4387 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4388 if(!learn_spellproto
)
4391 pet
->learnSpell(learn_spellproto
->Id
);
4393 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4394 _player
->PetSpellInitialize();
4397 void Spell::EffectTaunt(uint32
/*i*/)
4402 // this effect use before aura Taunt apply for prevent taunt already attacking target
4403 // for spell as marked "non effective at already attacking target"
4404 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4406 if (unitTarget
->getVictim()==m_caster
)
4408 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4413 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4414 if (unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4415 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4418 void Spell::EffectWeaponDmg(uint32 i
)
4422 if(!unitTarget
->isAlive())
4425 // multiple weapon dmg effect workaround
4426 // execute only the last weapon damage
4427 // and handle all effects at once
4428 for (int j
= 0; j
< 3; ++j
)
4430 switch(m_spellInfo
->Effect
[j
])
4432 case SPELL_EFFECT_WEAPON_DAMAGE
:
4433 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4434 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4435 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4436 if (j
< i
) // we must calculate only at last weapon effect
4442 // some spell specific modifiers
4443 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4445 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4446 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4447 bool normalized
= false;
4449 int32 spell_bonus
= 0; // bonus specific for spell
4450 switch(m_spellInfo
->SpellFamilyName
)
4452 case SPELLFAMILY_WARRIOR
:
4454 // Whirlwind, single only spell with 2 weapon white damage apply if have
4455 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000400000000)))
4457 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4458 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4460 // Devastate bonus and sunder armor refresh
4461 else if(m_spellInfo
->SpellVisual
[0] == 12295 && m_spellInfo
->SpellIconID
== 1508)
4464 // Need refresh all Sunder Armor auras from this caster
4465 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4466 SpellEntry
const *spellInfo
;
4467 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4469 spellInfo
= (*itr
).second
->GetSpellProto();
4470 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4471 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000)) &&
4472 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4474 (*itr
).second
->RefreshAura();
4475 stack
= (*itr
).second
->GetStackAmount();
4480 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4481 if (!stack
|| stack
< spellInfo
->StackAmount
)
4482 // Devastate causing Sunder Armor Effect
4483 // and no need to cast over max stack amount
4484 m_caster
->CastSpell(unitTarget
, 58567, true);
4488 case SPELLFAMILY_ROGUE
:
4490 // Mutilate (for each hand)
4491 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x600000000))
4495 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4500 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4501 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4503 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4512 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4515 else if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000)))
4517 Item
* weapon
= ((Player
*)m_caster
)->GetWeaponForAttack(m_attackType
,true);
4518 if (weapon
&& weapon
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_DAGGER
)
4519 totalDamagePercentMod
*= 1.5f
; // 150% to daggers
4523 case SPELLFAMILY_PALADIN
:
4525 // Seal of Command - receive benefit from Spell Damage and Healing
4526 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000002000000))
4528 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4529 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4530 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4534 case SPELLFAMILY_SHAMAN
:
4536 // Skyshatter Harness item set bonus
4538 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x001000000000))
4540 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4541 for(Unit::AuraList::const_iterator citr
= m_OverrideClassScript
.begin(); citr
!= m_OverrideClassScript
.end(); ++citr
)
4543 // Stormstrike AP Buff
4544 if ( (*citr
)->GetModifier()->m_miscvalue
== 5634 )
4546 m_caster
->CastSpell(m_caster
, 38430, true, NULL
, *citr
);
4553 case SPELLFAMILY_DEATHKNIGHT
:
4555 // Blood Strike, Heart Strike, Obliterate
4556 // Blood-Caked Strike, Scourge Strike
4557 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000001400000) ||
4558 m_spellInfo
->SpellIconID
== 1736 || m_spellInfo
->SpellIconID
== 3143)
4561 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4562 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4564 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
4565 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
4566 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
4572 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4573 double bonus
= count
* CalculateDamage(m_spellInfo
->SpellIconID
== 1736 ? 0 : 2, unitTarget
) / 100.0f
;
4574 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4575 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000000400000) ||
4576 m_spellInfo
->SpellIconID
== 1736)
4579 totalDamagePercentMod
+= bonus
;
4586 int32 fixed_bonus
= 0;
4587 for (int j
= 0; j
< 3; ++j
)
4589 switch(m_spellInfo
->Effect
[j
])
4591 case SPELL_EFFECT_WEAPON_DAMAGE
:
4592 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4593 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4595 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4596 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4599 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4600 weaponDamagePercentMod
*= float(CalculateDamage(j
, unitTarget
)) / 100.0f
;
4602 // applied only to prev.effects fixed damage
4603 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4606 break; // not weapon damage effect, just skip
4610 // apply weaponDamagePercentMod to spell bonus also
4611 if(spellBonusNeedWeaponDamagePercentMod
)
4612 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4614 // non-weapon damage
4615 int32 bonus
= spell_bonus
+ fixed_bonus
;
4617 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4621 switch(m_attackType
)
4624 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4625 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4626 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4629 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4630 bonus
= int32(bonus
*weapon_total_pct
);
4633 // + weapon damage with applied weapon% dmg to base weapon damage in call
4634 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4637 bonus
= int32(bonus
*totalDamagePercentMod
);
4639 // prevent negative damage
4640 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4642 // Add melee damage bonuses (also check for negative)
4643 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4644 m_damage
+= eff_damage
;
4647 if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x2000000)))
4649 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4650 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4654 if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==UI64LIT(0x0000040000000000)))
4656 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4657 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4661 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4663 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4665 // wands don't have ammo
4666 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_WAND
)
4669 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4671 if(pItem
->GetMaxStackCount()==1)
4673 // decrease durability for non-stackable throw weapon
4674 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4678 // decrease items amount for stackable throw weapon
4680 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4683 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4684 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4688 void Spell::EffectThreat(uint32
/*i*/)
4690 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4693 if(!unitTarget
->CanHaveThreatList())
4696 unitTarget
->AddThreat(m_caster
, float(damage
));
4699 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4703 if(!unitTarget
->isAlive())
4706 uint32 heal
= m_caster
->GetMaxHealth();
4711 void Spell::EffectInterruptCast(uint32
/*i*/)
4715 if(!unitTarget
->isAlive())
4718 // TODO: not all spells that used this effect apply cooldown at school spells
4719 // also exist case: apply cooldown to interrupted cast only and to all spells
4720 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; ++i
)
4722 if (Spell
* spell
= unitTarget
->GetCurrentSpell(CurrentSpellTypes(i
)))
4724 SpellEntry
const* curSpellInfo
= spell
->m_spellInfo
;
4725 // check if we can interrupt spell
4726 if ((curSpellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
) && curSpellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4728 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo
), GetSpellDuration(m_spellInfo
));
4729 unitTarget
->InterruptSpell(CurrentSpellTypes(i
),false);
4735 void Spell::EffectSummonObjectWild(uint32 i
)
4737 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4739 GameObject
* pGameObj
= new GameObject
;
4741 WorldObject
* target
= focusObject
;
4746 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4748 x
= m_targets
.m_destX
;
4749 y
= m_targets
.m_destY
;
4750 z
= m_targets
.m_destZ
;
4753 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
4755 Map
*map
= target
->GetMap();
4757 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4758 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4764 int32 duration
= GetSpellDuration(m_spellInfo
);
4766 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4767 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4769 // Wild object not have owner and check clickable by players
4772 if(pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4774 Player
*pl
= (Player
*)m_caster
;
4775 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4777 switch(pGameObj
->GetMapId())
4781 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4783 uint32 team
= ALLIANCE
;
4785 if(pl
->GetTeam() == team
)
4788 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4794 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4796 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4803 if(uint32 linkedEntry
= pGameObj
->GetGOInfo()->GetLinkedGameObjectEntry())
4805 GameObject
* linkedGO
= new GameObject
;
4806 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4807 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4809 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4810 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4812 // Wild object not have owner and check clickable by players
4824 void Spell::EffectScriptEffect(uint32 effIndex
)
4826 // TODO: we must implement hunter pet summon at login there (spell 6962)
4828 switch(m_spellInfo
->SpellFamilyName
)
4830 case SPELLFAMILY_GENERIC
:
4832 switch(m_spellInfo
->Id
)
4834 // PX-238 Winter Wondervolt TRAP
4837 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4840 for(int j
= 0; j
< 4; ++j
)
4841 if(unitTarget
->HasAura(spells
[j
],0))
4845 uint32 iTmpSpellId
= spells
[urand(0,3)];
4848 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4854 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4857 uint32 spell_id
= 0;
4860 case 1: spell_id
= 8854; break;
4861 default: spell_id
= 8855; break;
4864 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4867 // Brittle Armor - need remove one 24575 Brittle Armor aura
4869 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4871 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4873 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4875 // Orb teleport spells
4889 switch(m_spellInfo
->Id
)
4891 case 25140: spellid
= 32571; break;
4892 case 25143: spellid
= 32572; break;
4893 case 25650: spellid
= 30140; break;
4894 case 25652: spellid
= 30141; break;
4895 case 29128: spellid
= 32568; break;
4896 case 29129: spellid
= 32569; break;
4897 case 35376: spellid
= 25649; break;
4898 case 35727: spellid
= 35730; break;
4903 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4906 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4921 if(!unitTarget
|| !unitTarget
->isAlive())
4924 // Onyxia Scale Cloak
4925 if(unitTarget
->GetDummyAura(22683))
4929 m_caster
->CastSpell(unitTarget
, 22682, true);
4932 // Summon Black Qiraji Battle Tank
4938 // Prevent stacking of mounts
4939 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4941 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4942 if (unitTarget
->GetAreaId() == 3428)
4943 unitTarget
->CastSpell(unitTarget
, 25863, false);
4945 unitTarget
->CastSpell(unitTarget
, 26655, false);
4948 // Piccolo of the Flaming Fire
4951 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4953 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4956 // Demonic Empowerment (succubus Vanish effect)
4962 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4963 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4964 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
4965 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN
);
4974 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4975 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4978 // Mirren's Drinking Hat
4982 switch ( urand(1, 6) )
4987 item
= 23584; break; // Loch Modan Lager
4990 item
= 23585; break; // Stouthammer Lite
4992 item
= 23586; break; // Aerie Peak Pale Ale
4995 DoCreateItem(effIndex
,item
);
5003 // Removes snares and roots.
5004 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
5005 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5006 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
5010 Aura
*aur
= iter
->second
;
5011 if (!aur
->IsPositive()) //only remove negative spells
5013 // check for mechanic mask
5014 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
5016 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
5020 next
= Auras
.begin();
5032 unitTarget
->CastSpell(unitTarget
, 41131, true);
5035 // Force Cast - Portal Effect: Sunwell Isle
5041 unitTarget
->CastSpell(unitTarget
, 44870, true);
5044 // Goblin Weather Machine
5053 case 0: spellId
= 46740; break;
5054 case 1: spellId
= 46739; break;
5055 case 2: spellId
= 46738; break;
5056 case 3: spellId
= 46736; break;
5058 unitTarget
->CastSpell(unitTarget
, spellId
, true);
5064 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5067 ((Player
*)unitTarget
)->ModifyMoney(50000000);
5071 // Emblazon Runeblade
5077 unitTarget
->CastSpell(unitTarget
, 51771, false);
5083 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
5085 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5086 unitTarget
->CastSpell(unitTarget
, damage
, false);
5089 // Winged Steed of the Ebon Blade
5092 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5095 // Prevent stacking of mounts
5096 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
5098 // Triggered spell id dependent of riding skill
5099 if(uint16 skillval
= ((Player
*)unitTarget
)->GetSkillValue(SKILL_RIDING
))
5101 if (skillval
>= 300)
5102 unitTarget
->CastSpell(unitTarget
, 54727, true);
5104 unitTarget
->CastSpell(unitTarget
, 54726, true);
5108 case 55693: // Remove Collapsing Cave Aura
5111 unitTarget
->RemoveAurasDueToSpell(m_spellInfo
->CalculateSimpleValue(effIndex
));
5113 case 58418: // Portal to Orgrimmar
5114 case 58420: // Portal to Stormwind
5116 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
5119 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
5120 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
5122 if (((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
))
5123 unitTarget
->CastSpell(unitTarget
, spellID
, true);
5127 case 59317: // Teleporting
5128 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5132 if (((Player
*)unitTarget
)->GetAreaId() == 4637)
5133 unitTarget
->CastSpell(unitTarget
, 59316, true);
5136 unitTarget
->CastSpell(unitTarget
, 59314, true);
5139 // random spell learn instead placeholder
5140 case 60893: // Northrend Alchemy Research
5141 case 61177: // Northrend Inscription Research
5142 case 61288: // Minor Inscription Research
5143 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5144 case 64323: // Book of Glyph Mastery
5146 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5149 // learn random explicit discovery recipe (if any)
5150 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, (Player
*)m_caster
))
5151 ((Player
*)m_caster
)->learnSpell(discoveredSpell
, false);
5157 case SPELLFAMILY_WARLOCK
:
5159 switch(m_spellInfo
->Id
)
5161 // Healthstone creating spells
5175 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5176 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
5178 if((*i
)->GetId() == 18692)
5183 else if((*i
)->GetId() == 18693)
5190 static uint32
const itypes
[8][3] = {
5191 { 5512, 19004, 19005}, // Minor Healthstone
5192 { 5511, 19006, 19007}, // Lesser Healthstone
5193 { 5509, 19008, 19009}, // Healthstone
5194 { 5510, 19010, 19011}, // Greater Healthstone
5195 { 9421, 19012, 19013}, // Major Healthstone
5196 {22103, 22104, 22105}, // Master Healthstone
5197 {36889, 36890, 36891}, // Demonic Healthstone
5198 {36892, 36893, 36894} // Fel Healthstone
5201 switch(m_spellInfo
->Id
)
5204 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
5206 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
5208 itemtype
=itypes
[2][rank
];break; // Healthstone
5210 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
5212 itemtype
=itypes
[4][rank
];break; // Major Healthstone
5214 itemtype
=itypes
[5][rank
];break; // Master Healthstone
5216 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
5218 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
5222 DoCreateItem( effIndex
, itemtype
);
5225 // Demonic Empowerment
5230 uint32 entry
= unitTarget
->GetEntry();
5234 case 416: spellID
= 54444; break; //imp
5235 case 417: spellID
= 54509; break; //fellhunter
5236 case 1860: spellID
= 54443; break; //void
5237 case 1863: spellID
= 54435; break; //succubus
5238 case 17252: spellID
= 54508; break; //fellguard
5242 unitTarget
->CastSpell(unitTarget
,spellID
,true);
5245 // Everlasting Affliction
5248 // Need refresh caster corruption auras on target
5249 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
5250 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
5252 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5253 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
5254 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000002)) &&
5255 (*itr
).second
->GetCasterGUID()==m_caster
->GetGUID())
5256 (*itr
).second
->RefreshAura();
5263 case SPELLFAMILY_PRIEST
:
5265 switch(m_spellInfo
->Id
)
5267 // Pain and Suffering
5272 // Refresh Shadow Word: Pain on target
5273 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5274 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5276 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5277 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5278 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000008000)) &&
5279 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5281 (*itr
).second
->RefreshAura();
5292 case SPELLFAMILY_HUNTER
:
5294 switch(m_spellInfo
->Id
)
5302 int32 basePoint
= 0;
5303 Unit
* target
= unitTarget
;
5304 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5305 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5307 Aura
*aura
= (*i
).second
;
5308 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5310 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5311 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5312 if (!(familyFlag
& UI64LIT(0x000000800000C000)))
5314 // Refresh aura duration
5315 aura
->RefreshAura();
5317 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5318 if ((familyFlag
& UI64LIT(0x0000000000004000)) && aura
->GetEffIndex() == 0)
5320 spellId
= 53353; // 53353 Chimera Shot - Serpent
5321 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5323 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5324 if ((familyFlag
& UI64LIT(0x0000008000000000)) && aura
->GetEffIndex() == 0)
5326 spellId
= 53358; // 53358 Chimera Shot - Viper
5327 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5330 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5331 if (familyFlag
& UI64LIT(0x0000000000008000))
5332 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5333 // ?? nothing say in spell desc (possibly need addition check)
5334 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5335 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5337 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5341 m_caster
->CastCustomSpell(target
, spellId
, &basePoint
, 0, 0, false);
5344 case 53412: // Invigoration (pet triggered script, master targeted)
5349 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5350 for(Unit::AuraList::const_iterator i
= auras
.begin();i
!= auras
.end(); ++i
)
5352 // Invigoration (master talent)
5353 if ((*i
)->GetModifier()->m_miscvalue
== 8 && (*i
)->GetSpellProto()->SpellIconID
== 3487)
5355 if (roll_chance_i((*i
)->GetModifier()->m_amount
))
5357 unitTarget
->CastSpell(unitTarget
, 53398, true, NULL
, (*i
), m_caster
->GetGUID());
5369 case SPELLFAMILY_PALADIN
:
5371 // Judgement (seal trigger)
5372 if (m_spellInfo
->Category
== SPELLCATEGORY_JUDGEMENT
)
5374 if(!unitTarget
|| !unitTarget
->isAlive())
5376 uint32 spellId1
= 0;
5377 uint32 spellId2
= 0;
5379 // Judgement self add switch
5380 switch (m_spellInfo
->Id
)
5382 case 53407: spellId1
= 20184; break; // Judgement of Justice
5383 case 20271: // Judgement of Light
5384 case 57774: spellId1
= 20185; break; // Judgement of Light
5385 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5387 sLog
.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo
->Id
);
5390 // all seals have aura dummy in 2 effect
5391 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5392 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5394 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5395 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5396 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5398 spellId2
= (*itr
)->GetModifier()->m_amount
;
5399 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5405 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5407 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5411 case SPELLFAMILY_POTION
:
5413 switch(m_spellInfo
->Id
)
5420 unitTarget
->CastSpell(unitTarget
, 28694, true);
5428 // 25% chance of casting a random buff
5429 if(roll_chance_i(75))
5432 // triggered spells are 28703 to 28707
5433 // Note: some sources say, that there was the possibility of
5434 // receiving a debuff. However, this seems to be removed by a patch.
5435 const uint32 spellid
= 28703;
5437 // don't overwrite an existing aura
5438 for(uint8 i
= 0; i
< 5; ++i
)
5439 if(unitTarget
->HasAura(spellid
+ i
, 0))
5441 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5450 // 25% chance of casting Nightmare Pollen
5451 if(roll_chance_i(75))
5453 unitTarget
->CastSpell(unitTarget
, 28721, true);
5461 // normal DB scripted effect
5465 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5466 m_caster
->GetMap()->ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5469 void Spell::EffectSanctuary(uint32
/*i*/)
5473 //unitTarget->CombatStop();
5475 unitTarget
->CombatStop();
5476 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5477 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5478 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5480 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5484 void Spell::EffectAddComboPoints(uint32
/*i*/)
5489 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5495 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5498 void Spell::EffectDuel(uint32 i
)
5500 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5503 Player
*caster
= (Player
*)m_caster
;
5504 Player
*target
= (Player
*)unitTarget
;
5506 // caster or target already have requested duel
5507 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5510 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5511 // Don't have to check the target's map since you cannot challenge someone across maps
5512 uint32 mapid
= caster
->GetMapId();
5513 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5515 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5519 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5520 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5522 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5526 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5527 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5529 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5533 //CREATE DUEL FLAG OBJECT
5534 GameObject
* pGameObj
= new GameObject
;
5536 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5538 Map
*map
= m_caster
->GetMap();
5539 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5540 map
, m_caster
->GetPhaseMask(),
5541 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5542 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5543 m_caster
->GetPositionZ(),
5544 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
5550 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5551 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5552 int32 duration
= GetSpellDuration(m_spellInfo
);
5553 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5554 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5556 m_caster
->AddGameObject(pGameObj
);
5561 WorldPacket
data(SMSG_DUEL_REQUESTED
, 8 + 8);
5562 data
<< uint64(pGameObj
->GetGUID());
5563 data
<< uint64(caster
->GetGUID());
5564 caster
->GetSession()->SendPacket(&data
);
5565 target
->GetSession()->SendPacket(&data
);
5568 DuelInfo
*duel
= new DuelInfo
;
5569 duel
->initiator
= caster
;
5570 duel
->opponent
= target
;
5571 duel
->startTime
= 0;
5572 duel
->startTimer
= 0;
5573 caster
->duel
= duel
;
5575 DuelInfo
*duel2
= new DuelInfo
;
5576 duel2
->initiator
= caster
;
5577 duel2
->opponent
= caster
;
5578 duel2
->startTime
= 0;
5579 duel2
->startTimer
= 0;
5580 target
->duel
= duel2
;
5582 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5583 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5586 void Spell::EffectStuck(uint32
/*i*/)
5588 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5591 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5594 Player
* pTarget
= (Player
*)unitTarget
;
5596 sLog
.outDebug("Spell Effect: Stuck");
5597 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());
5599 if(pTarget
->isInFlight())
5602 // homebind location is loaded always
5603 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5605 // Stuck spell trigger Hearthstone cooldown
5606 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5609 Spell
spell(pTarget
, spellInfo
, true, 0);
5610 spell
.SendSpellCooldown();
5613 void Spell::EffectSummonPlayer(uint32
/*i*/)
5615 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5618 // Evil Twin (ignore player summon, but hide this for summoner)
5619 if(unitTarget
->GetDummyAura(23445))
5623 m_caster
->GetClosePoint(x
, y
, z
, unitTarget
->GetObjectSize());
5625 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5627 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5628 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5629 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5630 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5631 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5634 static ScriptInfo
generateActivateCommand()
5637 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5641 void Spell::EffectActivateObject(uint32 effect_idx
)
5646 static ScriptInfo activateCommand
= generateActivateCommand();
5648 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5650 gameObjTarget
->GetMap()->ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5653 void Spell::EffectApplyGlyph(uint32 i
)
5655 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5658 Player
*player
= (Player
*)m_caster
;
5661 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5663 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5665 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5667 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5669 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5670 return; // glyph slot mismatch
5675 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5677 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5679 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5680 player
->SetGlyph(m_glyphIndex
, 0);
5684 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5685 player
->SetGlyph(m_glyphIndex
, glyph
);
5686 player
->SendTalentsInfoData(false);
5691 void Spell::EffectSummonTotem(uint32 i
)
5694 switch(m_spellInfo
->EffectMiscValueB
[i
])
5696 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5697 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5698 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5699 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5700 // Battle standard case
5701 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5702 // jewelery statue case, like totem without slot
5703 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5707 if(slot
< MAX_TOTEM
)
5709 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5712 Creature
*OldTotem
= m_caster
->GetMap()->GetCreature(guid
);
5713 if(OldTotem
&& OldTotem
->isTotem())
5714 ((Totem
*)OldTotem
)->UnSummon();
5719 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5720 team
= ((Player
*)m_caster
)->GetTeam();
5722 Totem
* pTotem
= new Totem
;
5724 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5725 m_spellInfo
->EffectMiscValue
[i
], team
))
5731 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5734 m_caster
->GetClosePoint(x
, y
, z
, pTotem
->GetObjectSize(), 2.0f
, angle
);
5736 // totem must be at same Z in case swimming caster and etc.
5737 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5738 z
= m_caster
->GetPositionZ();
5740 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5742 if(slot
< MAX_TOTEM
)
5743 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5745 pTotem
->SetOwner(m_caster
->GetGUID());
5746 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5748 int32 duration
=GetSpellDuration(m_spellInfo
);
5749 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5750 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
5751 pTotem
->SetDuration(duration
);
5753 if (damage
) // if not spell info, DB values used
5755 pTotem
->SetMaxHealth(damage
);
5756 pTotem
->SetHealth(damage
);
5759 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5761 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5762 pTotem
->SetFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_PVP_ATTACKABLE
);
5764 if(m_caster
->IsPvP())
5765 pTotem
->SetPvP(true);
5767 pTotem
->Summon(m_caster
);
5769 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5771 WorldPacket
data(SMSG_TOTEM_CREATED
, 1 + 8 + 4 + 4);
5772 data
<< uint8(slot
);
5773 data
<< uint64(pTotem
->GetGUID());
5774 data
<< uint32(duration
);
5775 data
<< uint32(m_spellInfo
->Id
);
5776 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5780 void Spell::EffectEnchantHeldItem(uint32 i
)
5782 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5783 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5786 Player
* item_owner
= (Player
*)unitTarget
;
5787 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5793 if(!item
->IsEquipped())
5796 if (m_spellInfo
->EffectMiscValue
[i
])
5798 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5799 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5801 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5803 duration
= 10; //10 seconds for enchants which don't have listed duration
5805 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5809 // Always go to temp enchantment slot
5810 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5812 // Enchantment will not be applied if a different one already exists
5813 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5816 // Apply the temporary enchantment
5817 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
5818 item_owner
->ApplyEnchantment(item
, slot
, true);
5822 void Spell::EffectDisEnchant(uint32
/*i*/)
5824 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5827 Player
* p_caster
= (Player
*)m_caster
;
5828 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5831 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5833 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5835 // item will be removed at disenchanting end
5838 void Spell::EffectInebriate(uint32
/*i*/)
5840 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5843 Player
*player
= (Player
*)unitTarget
;
5844 uint16 currentDrunk
= player
->GetDrunkValue();
5845 uint16 drunkMod
= damage
* 256;
5846 if (currentDrunk
+ drunkMod
> 0xFFFF)
5847 currentDrunk
= 0xFFFF;
5849 currentDrunk
+= drunkMod
;
5850 player
->SetDrunkValue(currentDrunk
, m_CastItem
? m_CastItem
->GetEntry() : 0);
5853 void Spell::EffectFeedPet(uint32 i
)
5855 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5858 Player
*_player
= (Player
*)m_caster
;
5860 Item
* foodItem
= m_targets
.getItemTarget();
5864 Pet
*pet
= _player
->GetPet();
5871 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5876 _player
->DestroyItemCount(foodItem
,count
,true);
5877 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5879 m_caster
->CastCustomSpell(pet
, m_spellInfo
->EffectTriggerSpell
[i
], &benefit
, NULL
, NULL
, true);
5882 void Spell::EffectDismissPet(uint32
/*i*/)
5884 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5887 Pet
* pet
= m_caster
->GetPet();
5889 // not let dismiss dead pet
5890 if(!pet
||!pet
->isAlive())
5893 ((Player
*)m_caster
)->RemovePet(pet
, PET_SAVE_NOT_IN_SLOT
);
5896 void Spell::EffectSummonObject(uint32 i
)
5898 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5901 switch(m_spellInfo
->Effect
[i
])
5903 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5904 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5905 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5906 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5910 if(uint64 guid
= m_caster
->m_ObjectSlot
[slot
])
5912 if(GameObject
* obj
= m_caster
? m_caster
->GetMap()->GetGameObject(guid
) : NULL
)
5913 obj
->SetLootState(GO_JUST_DEACTIVATED
);
5914 m_caster
->m_ObjectSlot
[slot
] = 0;
5917 GameObject
* pGameObj
= new GameObject
;
5920 // If dest location if present
5921 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5923 x
= m_targets
.m_destX
;
5924 y
= m_targets
.m_destY
;
5925 z
= m_targets
.m_destZ
;
5927 // Summon in random point all other units if location present
5929 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
5931 Map
*map
= m_caster
->GetMap();
5932 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5933 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
5939 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5940 int32 duration
= GetSpellDuration(m_spellInfo
);
5941 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5942 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5943 m_caster
->AddGameObject(pGameObj
);
5946 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5947 data
<< uint64(pGameObj
->GetGUID());
5948 m_caster
->SendMessageToSet(&data
, true);
5950 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5953 void Spell::EffectResurrect(uint32
/*effIndex*/)
5957 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5960 if(unitTarget
->isAlive())
5962 if(!unitTarget
->IsInWorld())
5965 switch (m_spellInfo
->Id
)
5967 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5969 if (roll_chance_i(67))
5971 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5975 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5977 if (roll_chance_i(50))
5979 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5987 Player
* pTarget
= ((Player
*)unitTarget
);
5989 if(pTarget
->isRessurectRequested()) // already have one active request
5992 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5993 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5995 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5996 SendResurrectRequest(pTarget
);
5999 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
6001 if(!unitTarget
|| !unitTarget
->isAlive())
6004 if( unitTarget
->m_extraAttacks
)
6007 unitTarget
->m_extraAttacks
= damage
;
6010 void Spell::EffectParry(uint32
/*i*/)
6012 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6013 ((Player
*)unitTarget
)->SetCanParry(true);
6016 void Spell::EffectBlock(uint32
/*i*/)
6018 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6019 ((Player
*)unitTarget
)->SetCanBlock(true);
6022 void Spell::EffectLeapForward(uint32 i
)
6024 if(unitTarget
->isInFlight())
6027 if( m_spellInfo
->rangeIndex
== 1) //self range
6029 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6033 unitTarget
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
6035 unitTarget
->GetPosition(ox
, oy
, oz
);
6037 float fx2
, fy2
, fz2
; // getObjectHitPos overwrite last args in any result case
6038 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
6043 unitTarget
->UpdateGroundPositionZ(fx
, fy
, fz
);
6046 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(), unitTarget
== m_caster
);
6050 void Spell::EffectLeapBack(uint32 i
)
6052 if(unitTarget
->isInFlight())
6055 m_caster
->KnockBackFrom(unitTarget
,float(m_spellInfo
->EffectMiscValue
[i
])/10,float(damage
)/10);
6058 void Spell::EffectReputation(uint32 i
)
6060 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6063 Player
*_player
= (Player
*)unitTarget
;
6065 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
6067 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
6069 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
6074 _player
->GetReputationMgr().ModifyReputation(factionEntry
, rep_change
);
6077 void Spell::EffectQuestComplete(uint32 i
)
6079 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6082 Player
*_player
= (Player
*)m_caster
;
6084 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
6085 _player
->AreaExploredOrEventHappens(quest_id
);
6088 void Spell::EffectSelfResurrect(uint32 i
)
6090 if(!unitTarget
|| unitTarget
->isAlive())
6092 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6094 if(!unitTarget
->IsInWorld())
6103 health
= uint32(-damage
);
6104 mana
= m_spellInfo
->EffectMiscValue
[i
];
6109 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
6110 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
6111 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
6114 Player
*plr
= ((Player
*)unitTarget
);
6115 plr
->ResurrectPlayer(0.0f
);
6117 plr
->SetHealth( health
);
6118 plr
->SetPower(POWER_MANA
, mana
);
6119 plr
->SetPower(POWER_RAGE
, 0 );
6120 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
6122 plr
->SpawnCorpseBones();
6127 void Spell::EffectSkinning(uint32
/*i*/)
6129 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
6131 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
6134 Creature
* creature
= (Creature
*) unitTarget
;
6135 int32 targetLevel
= creature
->getLevel();
6137 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
6139 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
6140 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6142 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
6144 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
6146 // Double chances for elites
6147 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
6150 void Spell::EffectCharge(uint32
/*i*/)
6155 //TODO: research more ContactPoint/attack distance.
6156 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6158 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6160 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6161 ((Creature
*)unitTarget
)->StopMoving();
6163 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6164 m_caster
->SendMonsterMove(x
, y
, z
, 0, m_caster
->GetTypeId()==TYPEID_PLAYER
? MONSTER_MOVE_WALK
: ((Creature
*)m_caster
)->GetMonsterMoveFlags(), 1);
6166 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
6167 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
6169 // not all charge effects used in negative spells
6170 if (unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6171 m_caster
->Attack(unitTarget
,true);
6174 void Spell::EffectCharge2(uint32
/*i*/)
6177 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6179 x
= m_targets
.m_destX
;
6180 y
= m_targets
.m_destY
;
6181 z
= m_targets
.m_destZ
;
6183 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6184 ((Creature
*)unitTarget
)->StopMoving();
6186 else if (unitTarget
&& unitTarget
!= m_caster
)
6187 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6191 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6192 m_caster
->SendMonsterMove(x
, y
, z
, 0, m_caster
->GetTypeId()==TYPEID_PLAYER
? MONSTER_MOVE_WALK
: ((Creature
*)m_caster
)->GetMonsterMoveFlags(), 1);
6194 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
6195 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
6197 // not all charge effects used in negative spells
6198 if (unitTarget
&& unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6199 m_caster
->Attack(unitTarget
,true);
6202 void Spell::EffectSummonCritter(uint32 i
)
6204 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6206 Player
* player
= (Player
*)m_caster
;
6208 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
6212 Pet
* old_critter
= player
->GetMiniPet();
6214 // for same pet just despawn
6215 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
6217 player
->RemoveMiniPet();
6221 // despawn old pet before summon new
6223 player
->RemoveMiniPet();
6226 Pet
* critter
= new Pet(MINI_PET
);
6228 Map
*map
= m_caster
->GetMap();
6229 uint32 pet_number
= objmgr
.GeneratePetNumber();
6230 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
6231 pet_entry
, pet_number
))
6233 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
6239 // If dest location if present
6240 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6242 x
= m_targets
.m_destX
;
6243 y
= m_targets
.m_destY
;
6244 z
= m_targets
.m_destZ
;
6246 // Summon if dest location not present near caster
6248 m_caster
->GetClosePoint(x
, y
, z
, critter
->GetObjectSize());
6250 critter
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
6252 if(!critter
->IsPositionValid())
6254 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6255 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
6260 critter
->SetOwnerGUID(m_caster
->GetGUID());
6261 critter
->SetCreatorGUID(m_caster
->GetGUID());
6262 critter
->setFaction(m_caster
->getFaction());
6263 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
6265 critter
->AIM_Initialize();
6266 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6267 //critter->InitLevelupSpellsForLevel(); // none?
6268 critter
->SelectLevel(critter
->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6269 critter
->SetUInt32Value(UNIT_NPC_FLAGS
, critter
->GetCreatureInfo()->npcflag
);
6270 // some mini-pets have quests
6272 // set timer for unsummon
6273 int32 duration
= GetSpellDuration(m_spellInfo
);
6275 critter
->SetDuration(duration
);
6277 std::string name
= player
->GetName();
6278 name
.append(petTypeSuffix
[critter
->getPetType()]);
6279 critter
->SetName( name
);
6280 player
->SetMiniPet(critter
);
6282 map
->Add((Creature
*)critter
);
6285 void Spell::EffectKnockBack(uint32 i
)
6290 unitTarget
->KnockBackFrom(m_caster
,float(m_spellInfo
->EffectMiscValue
[i
])/10,float(damage
)/10);
6293 void Spell::EffectSendTaxi(uint32 i
)
6295 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6298 ((Player
*)unitTarget
)->ActivateTaxiPathTo(m_spellInfo
->EffectMiscValue
[i
],m_spellInfo
->Id
);
6301 void Spell::EffectPlayerPull(uint32 i
)
6306 unitTarget
->KnockBackFrom(m_caster
,float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
)),float(m_spellInfo
->EffectMiscValue
[i
])/10);
6309 void Spell::EffectDispelMechanic(uint32 i
)
6314 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6316 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6317 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6321 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6322 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6324 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6328 next
= Auras
.begin();
6334 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6336 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6338 Player
*_player
= (Player
*)m_caster
;
6339 Pet
*pet
= _player
->GetPet();
6346 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6347 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6348 pet
->setDeathState( ALIVE
);
6349 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6350 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6352 pet
->AIM_Initialize();
6354 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6355 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6358 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6361 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6363 if(!m_caster
->m_TotemSlot
[slot
])
6366 Creature
* totem
= m_caster
->GetMap()->GetCreature(m_caster
->m_TotemSlot
[slot
]);
6367 if(totem
&& totem
->isTotem())
6369 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6370 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6373 uint32 manacost
= m_caster
->GetCreateMana() * spellInfo
->ManaCostPercentage
/ 100;
6374 mana
+= manacost
* damage
/ 100;
6376 ((Totem
*)totem
)->UnSummon();
6381 m_caster
->CastCustomSpell(m_caster
, 39104, &mana
, NULL
, NULL
, true);
6384 void Spell::EffectDurabilityDamage(uint32 i
)
6386 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6389 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6391 // FIXME: some spells effects have value -1/-2
6392 // Possibly its mean -1 all player equipped items and -2 all items
6395 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
, (slot
< -1));
6399 // invalid slot value
6400 if(slot
>= INVENTORY_SLOT_BAG_END
)
6403 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6404 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
, damage
);
6407 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6409 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6412 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6414 // FIXME: some spells effects have value -1/-2
6415 // Possibly its mean -1 all player equipped items and -2 all items
6418 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
, (slot
< -1));
6422 // invalid slot value
6423 if(slot
>= INVENTORY_SLOT_BAG_END
)
6429 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6430 ((Player
*)unitTarget
)->DurabilityLoss(item
, double(damage
)/100.0f
);
6433 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6438 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6441 void Spell::EffectTransmitted(uint32 effIndex
)
6443 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6445 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6449 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6455 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6457 fx
= m_targets
.m_destX
;
6458 fy
= m_targets
.m_destY
;
6459 fz
= m_targets
.m_destZ
;
6461 //FIXME: this can be better check for most objects but still hack
6462 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6464 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6465 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6469 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6470 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6471 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6473 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6476 Map
*cMap
= m_caster
->GetMap();
6478 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6480 if ( !cMap
->IsInWater(fx
, fy
, fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6481 { // but this is not proper, we really need to ignore not materialized objects
6482 SendCastResult(SPELL_FAILED_NOT_HERE
);
6483 SendChannelUpdate(0);
6487 // replace by water level in this case
6488 fz
= cMap
->GetWaterLevel(fx
, fy
);
6490 // if gameobject is summoning object, it should be spawned right on caster's position
6491 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6493 m_caster
->GetPosition(fx
, fy
, fz
);
6496 GameObject
* pGameObj
= new GameObject
;
6498 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6499 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6505 int32 duration
= GetSpellDuration(m_spellInfo
);
6507 switch(goinfo
->type
)
6509 case GAMEOBJECT_TYPE_FISHINGNODE
:
6511 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6512 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6514 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6515 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6519 case 0: lastSec
= 3; break;
6520 case 1: lastSec
= 7; break;
6521 case 2: lastSec
= 13; break;
6522 case 3: lastSec
= 17; break;
6525 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6528 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6530 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
6532 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6533 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6537 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6538 case GAMEOBJECT_TYPE_CHEST
:
6543 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6545 pGameObj
->SetOwnerGUID(m_caster
->GetGUID());
6547 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel());
6548 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6550 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6551 //m_caster->AddGameObject(pGameObj);
6552 //m_ObjToDel.push_back(pGameObj);
6554 cMap
->Add(pGameObj
);
6556 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6557 data
<< uint64(pGameObj
->GetGUID());
6558 m_caster
->SendMessageToSet(&data
,true);
6560 if(uint32 linkedEntry
= pGameObj
->GetGOInfo()->GetLinkedGameObjectEntry())
6562 GameObject
* linkedGO
= new GameObject
;
6563 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6564 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6566 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6567 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel());
6568 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6569 linkedGO
->SetOwnerGUID(m_caster
->GetGUID());
6571 linkedGO
->GetMap()->Add(linkedGO
);
6582 void Spell::EffectProspecting(uint32
/*i*/)
6584 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6587 Player
* p_caster
= (Player
*)m_caster
;
6588 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6591 if(itemTarget
->GetCount() < 5)
6594 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6596 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6597 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6598 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6601 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6604 void Spell::EffectMilling(uint32
/*i*/)
6606 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6609 Player
* p_caster
= (Player
*)m_caster
;
6610 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6613 if(itemTarget
->GetCount() < 5)
6616 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6618 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6619 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6620 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6623 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6626 void Spell::EffectSkill(uint32
/*i*/)
6628 sLog
.outDebug("WORLD: SkillEFFECT");
6631 void Spell::EffectSummonDemon(uint32 i
)
6633 // select center of summon position
6634 float center_x
= m_targets
.m_destX
;
6635 float center_y
= m_targets
.m_destY
;
6636 float center_z
= m_targets
.m_destZ
;
6638 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6640 int32 amount
= damage
> 0 ? damage
: 1;
6642 if (m_spellInfo
->EffectMiscValueB
[i
] == SUMMON_TYPE_INFERNO
)
6645 for(int32 count
= 0; count
< amount
; ++count
)
6648 // If dest location if present
6649 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6651 // Summon 1 unit in dest location
6654 px
= m_targets
.m_destX
;
6655 py
= m_targets
.m_destY
;
6656 pz
= m_targets
.m_destZ
;
6658 // Summon in random point all other units if location present
6660 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
6662 // Summon if dest location not present near caster
6664 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
6666 int32 duration
= GetSpellDuration(m_spellInfo
);
6668 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,duration
);
6669 if (!Charmed
) // something fatal, not attempt more
6672 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6673 Charmed
->SetLevel(m_caster
->getLevel());
6675 // TODO: Add damage/mana/hp according to level
6677 // Enslave demon effect, without mana cost and cooldown
6678 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6680 // Enslave demon effect, without mana cost and cooldown
6681 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6683 // Inferno effect for non player calls
6684 if (m_spellInfo
->EffectMiscValueB
[i
]!=SUMMON_TYPE_INFERNO
)
6685 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6690 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6691 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6692 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6693 This is why we use a half sec delay between the visual effect and the resurrection itself */
6694 void Spell::EffectSpiritHeal(uint32
/*i*/)
6697 if(!unitTarget || unitTarget->isAlive())
6699 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6701 if(!unitTarget->IsInWorld())
6704 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6705 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6706 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6707 ((Player*)unitTarget)->SpawnCorpseBones();
6711 // remove insignia spell effect
6712 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6714 sLog
.outDebug("Effect: SkinPlayerCorpse");
6715 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6718 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6721 void Spell::EffectStealBeneficialBuff(uint32 i
)
6723 sLog
.outDebug("Effect: StealBeneficialBuff");
6725 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6728 std::vector
<Aura
*> steal_list
;
6729 // Create dispel mask by dispel type
6730 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6731 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6732 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6734 Aura
*aur
= (*itr
).second
;
6735 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6737 // Need check for passive? this
6738 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6739 steal_list
.push_back(aur
);
6742 // Ok if exist some buffs for dispel try dispel it
6743 if (!steal_list
.empty())
6745 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6746 int32 list_size
= steal_list
.size();
6747 // Dispell N = damage buffs (or while exist buffs for dispel)
6748 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6750 // Random select buff for dispel
6751 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6752 // Not use chance for steal
6753 // TODO possible need do it
6754 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6756 // Remove buff from list for prevent doubles
6757 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6760 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6762 j
= steal_list
.erase(j
);
6769 // Really try steal and send log
6770 if (!success_list
.empty())
6772 int32 count
= success_list
.size();
6773 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6774 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6775 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6776 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6777 data
<< uint8(0); // not used
6778 data
<< uint32(count
); // count
6779 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6781 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6782 data
<< uint32(spellInfo
->Id
); // Spell Id
6783 data
<< uint8(0); // 0 - steals !=0 transfers
6784 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6786 m_caster
->SendMessageToSet(&data
, true);
6791 void Spell::EffectKillCredit(uint32 i
)
6793 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6796 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6799 void Spell::EffectQuestFail(uint32 i
)
6801 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6804 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6807 void Spell::EffectActivateRune(uint32 eff_idx
)
6809 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6812 Player
*plr
= (Player
*)m_caster
;
6814 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6817 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6819 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6821 plr
->SetRuneCooldown(j
, 0);
6826 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6828 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6829 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6832 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6834 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6835 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6838 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);
6841 void Spell::EffectPlayMusic(uint32 i
)
6843 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6846 uint32 soundid
= m_spellInfo
->EffectMiscValue
[i
];
6848 if (!sSoundEntriesStore
.LookupEntry(soundid
))
6850 sLog
.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid
,m_spellInfo
->Id
);
6854 WorldPacket
data(SMSG_PLAY_MUSIC
, 4);
6855 data
<< uint32(soundid
);
6856 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);