2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
24 #include "UpdateMask.h"
26 #include "ObjectMgr.h"
29 #include "SkillExtraItems.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
51 #include "SocialMgr.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
58 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
60 &Spell::EffectNULL
, // 0
61 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump
, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL
, //154 unused
215 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32
/*i*/)
224 sLog
.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32
/*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i
)
234 if(!unitTarget
|| unitTarget
->isAlive())
237 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
240 if(!unitTarget
->IsInWorld())
243 Player
* pTarget
= ((Player
*)unitTarget
);
245 if(pTarget
->isRessurectRequested()) // already have one active request
248 uint32 health
= damage
;
249 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
250 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
251 SendResurrectRequest(pTarget
);
254 void Spell::EffectInstaKill(uint32
/*i*/)
256 if( !unitTarget
|| !unitTarget
->isAlive() )
260 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
262 uint32 entry
= unitTarget
->GetEntry();
266 case 416: spellID
=18789; break; //imp
267 case 417: spellID
=18792; break; //fellhunter
268 case 1860: spellID
=18790; break; //void
269 case 1863: spellID
=18791; break; //succubus
270 case 17252: spellID
=35701; break; //fellguard
272 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
276 m_caster
->CastSpell(m_caster
,spellID
,true);
279 if(m_caster
==unitTarget
) // prevent interrupt message
282 uint32 health
= unitTarget
->GetHealth();
283 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i
)
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage
= m_spellInfo
->CalculateSimpleValue(i
);
296 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
298 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
299 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
300 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
,damage
);
303 void Spell::EffectSchoolDMG(uint32 effect_idx
)
305 if( unitTarget
&& unitTarget
->isAlive())
307 switch(m_spellInfo
->SpellFamilyName
)
309 case SPELLFAMILY_GENERIC
:
312 if(m_spellInfo
->SpellIconID
== 2269 )
314 damage
+= rand()%2 ? damage
: 0;
317 switch(m_spellInfo
->Id
) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
330 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
331 if(ihit
->effectMask
& (1<<effect_idx
))
334 damage
/= count
; // divide to all targets
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage
= unitTarget
->GetHealth() / 2;
345 // Intercept (warrior spell trigger)
349 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
356 case SPELLFAMILY_MAGE
:
359 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
361 m_caster
->CastSpell(m_caster
,36032,true);
365 case SPELLFAMILY_WARRIOR
:
368 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
370 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
373 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000020000000000LL
)
374 damage
+= int32(m_caster
->GetShieldBlockValue());
376 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
378 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
379 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
383 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
386 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
390 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
392 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
397 case SPELLFAMILY_WARLOCK
:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
404 damage
+= int32(damage
*0.25f
);
408 case SPELLFAMILY_PRIEST
:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
412 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
415 case SPELLFAMILY_DRUID
:
418 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
422 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
423 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
424 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
425 m_caster
->SetPower(POWER_ENERGY
,0);
428 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
430 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
433 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
435 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
439 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
441 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
442 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
443 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
445 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
451 case SPELLFAMILY_ROGUE
:
454 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
462 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
463 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
464 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
465 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
470 // count consumed deadly poison doses at target
473 uint32 spellId
= poison
->GetId();
474 uint32 doses
= poison
->GetStackAmount();
477 for (int i
=0; i
< doses
; i
++)
478 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
480 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster
->GetDummyAura(37169))
484 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
488 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
490 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
492 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
493 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster
->GetDummyAura(37169))
501 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
503 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
506 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
508 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
511 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
513 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
517 case SPELLFAMILY_HUNTER
:
520 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
522 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
525 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
527 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
530 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
532 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
535 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
537 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
538 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
540 // Explosive Trap Effect
541 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
543 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
547 case SPELLFAMILY_PALADIN
:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
552 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
553 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
554 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
555 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
558 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
559 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
560 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
562 stacks
= (*itr
)->GetStackAmount();
565 // + 10% for each application of Holy Vengeance on the target
567 damage
+= damage
* stacks
* 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
572 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
573 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
574 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
575 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
580 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
581 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
582 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
583 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
588 // Add main hand dps * effect[2] amount
589 float averange
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
590 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
591 damage
+= count
* int32(averange
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
593 // Shield of Righteousness
594 else if(m_spellInfo
->SpellFamilyFlags
&0x0010000000000000LL
)
596 damage
+=int32(m_caster
->GetShieldBlockValue());
607 void Spell::EffectDummy(uint32 i
)
609 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
612 // selection by spell family
613 switch(m_spellInfo
->SpellFamilyName
)
615 case SPELLFAMILY_GENERIC
:
617 switch(m_spellInfo
->Id
)
619 case 8063: // Deviate Fish
621 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
627 case 1: spell_id
= 8064; break; // Sleepy
628 case 2: spell_id
= 8065; break; // Invigorate
629 case 3: spell_id
= 8066; break; // Shrink
630 case 4: spell_id
= 8067; break; // Party Time!
631 case 5: spell_id
= 8068; break; // Healthy Spirit
633 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
636 case 8213: // Savory Deviate Delight
638 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
645 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
647 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
649 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
657 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
671 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
673 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
675 switch (m_spellInfo
->Id
)
677 case 12850: damage
*= 0.2f
; break;
678 case 12162: damage
*= 0.4f
; break;
679 case 12868: damage
*= 0.6f
; break;
681 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
685 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
686 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
689 case 13120: // net-o-matic
696 uint32 roll
= urand(0, 99);
698 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
700 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
705 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell
|| !unitTarget
)
714 switch(m_triggeredByAuraSpell
->Id
)
716 case 26467: // Persistent Shield
717 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
720 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
731 Creature
* creatureTarget
= (Creature
*)unitTarget
;
732 creatureTarget
->setDeathState(JUST_DIED
);
733 creatureTarget
->RemoveCorpse();
734 creatureTarget
->SetHealth(0); // just for nice GM-mode view
737 case 16589: // Noggenfogger Elixir
739 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
745 case 1: spell_id
= 16595; break;
746 case 2: spell_id
= 16593; break;
747 default:spell_id
= 16591; break;
750 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
753 case 17251: // Spirit Healer Res
755 if(!unitTarget
|| !m_originalCaster
)
758 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
760 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
761 data
<< unitTarget
->GetGUID();
762 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
766 case 17271: // Test Fetid Skull
768 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
771 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
773 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
776 case 20577: // Cannibalize
778 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
785 Creature
* creatureTarget
= (Creature
*)unitTarget
;
786 if(creatureTarget
->isPet())
789 GameObject
* pGameObj
= new GameObject
;
791 Map
*map
= creatureTarget
->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
795 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
796 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1) )
802 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
803 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
804 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
805 pGameObj
->SetSpellId(m_spellInfo
->Id
);
807 creatureTarget
->setDeathState(JUST_DIED
);
808 creatureTarget
->RemoveCorpse();
809 creatureTarget
->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
814 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
815 data
<< uint64(pGameObj
->GetGUID());
816 m_caster
->SendMessageToSet(&data
,true);
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem
) return;
822 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem
) return;
826 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem
) return;
830 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem
) return;
834 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r
= irand(0, 119);
839 if ( r
< 20 ) // 1/6 polymorph
840 m_caster
->CastSpell(m_caster
,23444,true);
841 else if ( r
< 100 ) // 4/6 evil twin
842 m_caster
->CastSpell(m_caster
,23445,true);
843 else // 1/6 miss the target
844 m_caster
->CastSpell(m_caster
,36902,true);
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster
->CastSpell(m_caster
,23441,true);
851 m_caster
->CastSpell(m_caster
,23446,true);
853 case 23645: // Hourglass Sand
854 m_caster
->RemoveAurasDueToSpell(23170);
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster
->CastSpell(m_caster
,23782,true);
858 m_caster
->CastSpell(m_caster
,23783,true);
860 case 25860: // Reindeer Transformation
862 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
865 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
866 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
868 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed
>= 4.1f
)
872 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
873 else if (flyspeed
>= 3.8f
)
874 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
875 else if (flyspeed
>= 1.6f
)
876 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
877 else if (speed
>= 2.0f
)
878 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
880 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
889 m_caster
->CastSpell(unitTarget
,29294,true);
892 case 28730: // Arcane Torrent (Mana)
894 Aura
* dummy
= m_caster
->GetDummyAura(28734);
897 int32 bp
= damage
* dummy
->GetStackAmount();
898 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
899 m_caster
->RemoveAurasDueToSpell(28734);
903 case 29200: // Purify Helboar Meat
905 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
908 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
910 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
913 case 29858: // Soulshatter
914 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
915 m_caster
->CastSpell(unitTarget
,32835,true);
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem
) return;
919 if(roll_chance_i(86)) // success
920 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
921 else // backfire in 14% casts
922 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
924 case 30507: // Poultryizer
925 if (!m_CastItem
) return;
926 if(roll_chance_i(80)) // success
927 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
929 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
931 case 33060: // Make a Wish
933 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
940 case 1: spell_id
= 33053; break;
941 case 2: spell_id
= 33057; break;
942 case 3: spell_id
= 33059; break;
943 case 4: spell_id
= 33062; break;
944 case 5: spell_id
= 33064; break;
947 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
953 switch(m_caster
->GetAreaId())
955 case 3900: spell_id
= 35743; break;
956 case 3742: spell_id
= 35744; break;
960 m_caster
->CastSpell(m_caster
,spell_id
,true);
963 case 37674: // Chaos Blast
968 int32 basepoints0
= 100;
969 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
978 case 1: newitemid
= 32688; break;
979 case 2: newitemid
= 32689; break;
980 case 3: newitemid
= 32690; break;
981 case 4: newitemid
= 32691; break;
982 case 5: newitemid
= 32692; break;
983 case 6: newitemid
= 32693; break;
984 case 7: newitemid
= 32700; break;
985 case 8: newitemid
= 32701; break;
986 case 9: newitemid
= 32702; break;
987 case 10: newitemid
= 32703; break;
988 case 11: newitemid
= 32704; break;
989 case 12: newitemid
= 32705; break;
990 case 13: newitemid
= 32706; break;
991 case 14: newitemid
= 32707; break;
992 case 15: newitemid
= 32708; break;
993 case 16: newitemid
= 32709; break;
994 case 17: newitemid
= 32710; break;
995 case 18: newitemid
= 32711; break;
996 case 19: newitemid
= 32712; break;
997 case 20: newitemid
= 32713; break;
1002 DoCreateItem(i
,newitemid
);
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1021 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1023 creatureTarget
->setDeathState(JUST_DIED
);
1024 creatureTarget
->RemoveCorpse();
1025 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1031 case 34665: //Administer Antidote
1033 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1039 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1043 uint32 health
= tempSummon
->GetHealth();
1045 float x
= tempSummon
->GetPositionX();
1046 float y
= tempSummon
->GetPositionY();
1047 float z
= tempSummon
->GetPositionZ();
1048 float o
= tempSummon
->GetOrientation();
1049 tempSummon
->UnSummon();
1051 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1055 pCreature
->SetHealth(health
);
1056 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992,pCreature
);
1058 if (pCreature
->AI())
1059 pCreature
->AI()->AttackStart(m_caster
);
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster
->CastSpell(m_caster
, 45009, true);
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster
->CastSpell(m_caster
, 45088, true);
1075 case 50243: // Teach Language
1077 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1083 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1085 // 1000001 - gnomish binary
1086 m_caster
->CastSpell(m_caster
, 50242, true);
1090 // 01001000 - goblin binary
1091 m_caster
->CastSpell(m_caster
, 50246, true);
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1101 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1102 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1104 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1113 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1114 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1116 if (m_caster
->HasAura(reqAuraID
,0))
1117 m_caster
->CastSpell(m_caster
,spellID
,true,NULL
);
1121 return; // additional data for dummy[0]
1128 m_caster
->CastSpell(m_caster
,54586,true);
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo
->SpellIconID
)
1139 // Berserking (troll racial traits)
1142 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1143 int32 melee_mod
= 10;
1144 if (healthPerc
<= 40)
1146 if (healthPerc
< 100 && healthPerc
> 40)
1147 melee_mod
= 10+(100-healthPerc
)/3;
1149 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1
= (5-melee_mod
);
1151 int32 hasteModBasePoints2
= 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1155 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1161 case SPELLFAMILY_MAGE
:
1162 switch(m_spellInfo
->Id
)
1164 case 11958: // Cold Snap
1166 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1173 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1176 uint32 classspell
= itr
->first
;
1177 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1179 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1180 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1181 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1183 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1185 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1186 data
<< uint32(classspell
);
1187 data
<< uint64(m_caster
->GetGUID());
1188 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1195 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1205 case SPELLFAMILY_WARRIOR
:
1207 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1209 int32 chargeBasePoints0
= damage
;
1210 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1214 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1219 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1220 // Glyph of Execution bonus
1221 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1222 rage
+=aura
->GetModifier()->m_amount
;
1224 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1225 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1226 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1227 m_caster
->SetPower(POWER_RAGE
,0);
1231 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1235 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1239 switch(m_spellInfo
->Id
)
1246 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1252 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1253 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1259 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1264 case SPELLFAMILY_WARLOCK
:
1266 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1268 // In 303 exist spirit depend
1269 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1270 switch (m_spellInfo
->Id
)
1272 case 1454: damage
+=spirit
; break;
1273 case 1455: damage
+=spirit
*15/10; break;
1274 case 1456: damage
+=spirit
*2; break;
1275 case 11687: damage
+=spirit
*25/10; break;
1279 case 57946: damage
+=spirit
*3; break;
1281 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1284 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1285 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1286 if(int32(unitTarget
->GetHealth()) > damage
)
1288 // Shouldn't Appear in Combat Log
1289 unitTarget
->ModifyHealth(-damage
);
1291 int32 mana
= damage
;
1292 // Improved Life Tap mod
1293 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1294 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1296 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1297 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1299 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1302 int32 manaFeedVal
= 0;
1303 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1304 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1306 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1307 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1311 manaFeedVal
= manaFeedVal
* mana
/ 100;
1312 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1316 SendCastResult(SPELL_FAILED_FIZZLE
);
1320 case SPELLFAMILY_PRIEST
:
1322 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1329 switch(m_spellInfo
->Id
)
1331 case 47540: hurt
= 47758; heal
= 47757; break;
1332 case 53005: hurt
= 53001; heal
= 52986; break;
1333 case 53006: hurt
= 53002; heal
= 52987; break;
1334 case 53007: hurt
= 53003; heal
= 52988; break;
1336 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1339 if (m_caster
->IsFriendlyTo(unitTarget
))
1340 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1342 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1346 case SPELLFAMILY_DRUID
:
1348 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000100LL
)
1350 //Shapeshifting into an animal form or mounting cancels the effect.
1351 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1353 if(m_triggeredByAuraSpell
)
1354 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1358 //Any effect which causes you to lose control of your character will supress the starfall effect.
1359 if(m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1362 switch(m_spellInfo
->Id
)
1364 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1365 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1366 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1367 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1369 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1374 case SPELLFAMILY_ROGUE
:
1375 switch(m_spellInfo
->Id
)
1379 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1382 Player
*pCaster
= ((Player
*)m_caster
);
1384 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1388 // all poison enchantments is temporary
1389 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1393 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1397 for (int s
=0;s
<3;s
++)
1399 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1402 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1403 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1406 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1409 m_caster
->CastSpell(unitTarget
, 5940, true);
1412 case 14185: // Preparation Rogue
1414 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1417 //immediately finishes the cooldown on certain Rogue abilities
1418 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1419 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1421 uint32 classspell
= itr
->first
;
1422 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1424 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1426 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1428 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1429 data
<< uint32(classspell
);
1430 data
<< uint64(m_caster
->GetGUID());
1431 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1436 case 31231: // Cheat Death
1438 m_caster
->CastSpell(m_caster
,45182,true);
1443 case SPELLFAMILY_HUNTER
:
1445 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1447 if( !unitTarget
|| !unitTarget
->isAlive())
1452 // check dazed affect
1453 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1454 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1456 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1468 switch(m_spellInfo
->Id
)
1470 case 23989: //Readiness talent
1472 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1475 //immediately finishes the cooldown for hunter abilities
1476 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1477 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1479 uint32 classspell
= itr
->first
;
1480 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1482 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1484 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1486 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1487 data
<< uint32(classspell
);
1488 data
<< uint64(m_caster
->GetGUID());
1489 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1494 case 37506: // Scatter Shot
1496 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1499 // break Auto Shot and autohit
1500 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1501 m_caster
->AttackStop();
1502 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1507 case SPELLFAMILY_PALADIN
:
1508 switch(m_spellInfo
->SpellIconID
)
1510 case 156: // Holy Shock
1518 switch(m_spellInfo
->Id
)
1520 case 20473: hurt
= 25912; heal
= 25914; break;
1521 case 20929: hurt
= 25911; heal
= 25913; break;
1522 case 20930: hurt
= 25902; heal
= 25903; break;
1523 case 27174: hurt
= 27176; heal
= 27175; break;
1524 case 33072: hurt
= 33073; heal
= 33074; break;
1525 case 48824: hurt
= 48822; heal
= 48820; break;
1526 case 48825: hurt
= 48823; heal
= 48821; break;
1528 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1532 if(m_caster
->IsFriendlyTo(unitTarget
))
1533 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1535 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1539 case 561: // Judgement of command
1544 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1545 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1549 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1551 // decreased damage (/2) for non-stunned target.
1552 SpellModifier
*mod
= new SpellModifier
;
1553 mod
->op
= SPELLMOD_DAMAGE
;
1555 mod
->type
= SPELLMOD_PCT
;
1556 mod
->spellId
= m_spellInfo
->Id
;
1557 mod
->mask
= 0x0000020000000000LL
;
1560 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1561 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1563 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1566 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1572 switch(m_spellInfo
->Id
)
1574 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1579 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1582 case 31789: // Righteous Defense (step 1)
1584 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1586 // non-standard cast requirement check
1587 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1589 // clear cooldown at fail
1590 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1592 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1594 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1595 data
<< uint32(m_spellInfo
->Id
);
1596 data
<< uint64(m_caster
->GetGUID());
1597 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1600 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1604 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1605 // Clear targets for eff 1
1606 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1607 ihit
->effectMask
&= ~(1<<1);
1609 // not empty (checked)
1610 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1612 // chance to be selected from list
1613 float chance
= 100.0f
/attackers
.size();
1615 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1617 if(!roll_chance_f(chance
))
1620 AddUnitTarget((*aItr
), 1);
1623 // now let next effect cast spell at each target.
1626 case 37877: // Blessing of Faith
1631 uint32 spell_id
= 0;
1632 switch(unitTarget
->getClass())
1634 case CLASS_DRUID
: spell_id
= 37878; break;
1635 case CLASS_PALADIN
: spell_id
= 37879; break;
1636 case CLASS_PRIEST
: spell_id
= 37880; break;
1637 case CLASS_SHAMAN
: spell_id
= 37881; break;
1638 default: return; // ignore for not healing classes
1641 m_caster
->CastSpell(m_caster
,spell_id
,true);
1646 case SPELLFAMILY_SHAMAN
:
1647 //Shaman Rockbiter Weapon
1648 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1650 // TODO: use expect spell for enchant (if exist talent)
1651 // In 3.0.3 no mods present for rockbiter
1652 uint32 spell_id
= 0;
1653 switch(m_spellInfo
->Id
)
1655 case 8017: spell_id
= 36494; break; // Rank 1
1656 case 8018: spell_id
= 36750; break; // Rank 2
1657 case 8019: spell_id
= 36755; break; // Rank 3
1658 case 10399: spell_id
= 36759; break; // Rank 4
1660 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1664 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1668 sLog
.outError("WORLD: unknown spell id %i", spell_id
);
1672 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1675 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1677 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1679 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1681 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1683 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1684 // at calculation applied affect from Elemental Weapons talent
1685 // real enchantment damage-1
1686 spell
->m_currentBasePoints
[1] = damage
-1;
1688 SpellCastTargets targets
;
1689 targets
.setItemTarget( item
);
1690 spell
->prepare(&targets
);
1696 // Healing Stream Totem
1697 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1699 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1702 // Mana Spring Totem
1703 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1705 if(unitTarget
->getPowerType()!=POWER_MANA
)
1707 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1710 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1712 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1714 // Glyph of Mana Tide
1715 Unit
*owner
= m_caster
->GetOwner();
1717 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1718 damage
+=dummy
->GetModifier()->m_amount
;
1719 // Regenerate 6% of Total Mana Every 3 secs
1720 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1721 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1725 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1727 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1729 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1732 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1733 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1734 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1736 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1737 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1738 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1740 m_damage
+= m_damage
* damage
/ 100;
1748 case SPELLFAMILY_DEATHKNIGHT
:
1750 if(m_spellInfo
->SpellFamilyFlags
& 0x002000LL
)
1752 if(m_caster
->IsFriendlyTo(unitTarget
))
1754 if(unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1757 // first rank have special multiplier
1758 int32 bp
= damage
* 1.5f
;
1759 m_caster
->CastCustomSpell(unitTarget
,47633,&bp
,NULL
,NULL
,true);
1763 // first rank have special multiplier
1765 m_caster
->CastCustomSpell(unitTarget
,47632,&bp
,NULL
,NULL
,true);
1773 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1775 m_caster
->AddPetAura(petSpell
);
1779 // Script based implementation. Must be used only for not good for implementation in core spell effects
1780 // So called only for not proccessed cases
1782 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
1783 else if(unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
1784 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
1786 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
1789 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1791 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1794 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1798 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1803 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1806 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1808 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1809 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1813 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1818 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1820 SpellCastTargets targets
;
1821 targets
.setUnitTarget( unitTarget
);
1822 spell
->prepare(&targets
);
1824 m_caster
->SetCurrentCastedSpell(spell
);
1825 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1829 void Spell::EffectForceCast(uint32 i
)
1834 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1837 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1841 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1845 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1848 void Spell::EffectTriggerSpell(uint32 i
)
1850 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1853 switch(triggered_spell_id
)
1858 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1859 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1860 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1862 // if this spell is given to NPC it must handle rest by it's own AI
1863 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1866 // get highest rank of the Stealth spell
1868 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1869 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1871 // only highest rank is shown in spell book, so simply check if shown in spell book
1872 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1875 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1879 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1881 spellId
= spellInfo
->Id
;
1886 // no Stealth spell found
1890 // reset cooldown on it if needed
1891 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1892 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1894 m_caster
->CastSpell(m_caster
, spellId
, true);
1898 case 23770: // Sayge's Dark Fortune of *
1899 // not exist, common cooldown can be implemented in scripts if need.
1901 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1904 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1908 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1909 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1912 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1915 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1919 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1920 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1923 // Righteous Defense
1926 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1932 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1933 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1935 // remove all harmful spells on you...
1936 if( // ignore positive and passive auras
1937 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1938 // ignore physical auras
1939 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1941 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1942 iter
= Auras
.begin();
1947 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1950 if (Unit
*pet
= m_caster
->GetPet())
1951 pet
->CastSpell(pet
, 28305, true);
1957 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1961 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1965 // some triggered spells require specific equipment
1966 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1968 // main hand weapon required
1969 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1971 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1973 // skip spell if no weapon in slot or broken
1974 if(!item
|| item
->IsBroken() )
1977 // skip spell if weapon not fit to triggered spell
1978 if(!item
->IsFitToSpellRequirements(spellInfo
))
1982 // offhand hand weapon required
1983 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1985 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1987 // skip spell if no weapon in slot or broken
1988 if(!item
|| item
->IsBroken() )
1991 // skip spell if weapon not fit to triggered spell
1992 if(!item
->IsFitToSpellRequirements(spellInfo
))
1997 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1998 bool instant
= false;
1999 for(uint32 j
= i
+1; j
< 3; ++j
)
2001 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
2011 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
2014 m_TriggerSpells
.push_back(spellInfo
);
2017 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2019 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2022 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2026 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2027 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2032 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2034 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2037 void Spell::EffectJump(uint32 i
)
2039 if(m_caster
->isInFlight())
2042 // Init dest coordinates
2044 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2046 x
= m_targets
.m_destX
;
2047 y
= m_targets
.m_destY
;
2048 z
= m_targets
.m_destZ
;
2050 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2052 // explicit cast data from client or server-side cast
2053 // some spell at client send caster
2054 Unit
* pTarget
= NULL
;
2055 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2056 pTarget
= m_targets
.getUnitTarget();
2057 else if(unitTarget
->getVictim())
2058 pTarget
= m_caster
->getVictim();
2059 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2060 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2062 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2065 o
= m_caster
->GetOrientation();
2069 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2070 o
= m_caster
->GetOrientation();
2072 else if(gameObjTarget
)
2074 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2075 o
= m_caster
->GetOrientation();
2079 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2083 m_caster
->NearTeleportTo(x
,y
,z
,o
,true);
2086 void Spell::EffectTeleportUnits(uint32 i
)
2088 if(!unitTarget
|| unitTarget
->isInFlight())
2091 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2093 case TARGET_INNKEEPER_COORDINATES
:
2095 // Only players can teleport to innkeeper
2096 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2099 ((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);
2102 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2104 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2107 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2111 if(st
->target_mapId
==unitTarget
->GetMapId())
2112 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2113 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2114 ((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);
2117 case TARGET_BEHIND_VICTIM
:
2119 Unit
*pTarget
= NULL
;
2121 // explicit cast data from client or server-side cast
2122 // some spell at client send caster
2123 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2124 pTarget
= m_targets
.getUnitTarget();
2125 else if(unitTarget
->getVictim())
2126 pTarget
= unitTarget
->getVictim();
2127 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2128 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2130 // Init dest coordinates
2131 float x
= m_targets
.m_destX
;
2132 float y
= m_targets
.m_destY
;
2133 float z
= m_targets
.m_destZ
;
2134 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2135 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2140 // If not exist data for dest location - return
2141 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2143 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2146 // Init dest coordinates
2147 uint32 mapid
= m_caster
->GetMapId();
2148 float x
= m_targets
.m_destX
;
2149 float y
= m_targets
.m_destY
;
2150 float z
= m_targets
.m_destZ
;
2151 float orientation
= unitTarget
->GetOrientation();
2153 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2158 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2159 switch ( m_spellInfo
->Id
)
2161 // Dimensional Ripper - Everlook
2164 int32 r
= irand(0, 119);
2165 if ( r
>= 70 ) // 7/12 success
2167 if ( r
< 100 ) // 4/12 evil twin
2168 m_caster
->CastSpell(m_caster
,23445,true);
2170 m_caster
->CastSpell(m_caster
,23449,true);
2174 // Ultrasafe Transporter: Toshley's Station
2177 if ( roll_chance_i(50) ) // 50% success
2179 int32 rand_eff
= urand(1,7);
2183 // soul split - evil
2184 m_caster
->CastSpell(m_caster
,36900,true);
2187 // soul split - good
2188 m_caster
->CastSpell(m_caster
,36901,true);
2191 // Increase the size
2192 m_caster
->CastSpell(m_caster
,36895,true);
2195 // Decrease the size
2196 m_caster
->CastSpell(m_caster
,36893,true);
2201 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2202 m_caster
->CastSpell(m_caster
,36897,true);
2204 m_caster
->CastSpell(m_caster
,36899,true);
2209 m_caster
->CastSpell(m_caster
,36940,true);
2213 m_caster
->CastSpell(m_caster
,23445,true);
2219 // Dimensional Ripper - Area 52
2222 if ( roll_chance_i(50) ) // 50% success
2224 int32 rand_eff
= urand(1,4);
2228 // soul split - evil
2229 m_caster
->CastSpell(m_caster
,36900,true);
2232 // soul split - good
2233 m_caster
->CastSpell(m_caster
,36901,true);
2236 // Increase the size
2237 m_caster
->CastSpell(m_caster
,36895,true);
2242 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2243 m_caster
->CastSpell(m_caster
,36897,true);
2245 m_caster
->CastSpell(m_caster
,36899,true);
2255 void Spell::EffectApplyAura(uint32 i
)
2260 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2261 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2262 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2265 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2269 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2271 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2273 // Now Reduce spell duration using data received at spell hit
2274 int32 duration
= Aur
->GetAuraMaxDuration();
2275 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2276 Aur
->setDiminishGroup(m_diminishGroup
);
2278 // if Aura removed and deleted, do not continue.
2279 if(duration
== 0 && !(Aur
->IsPermanent()))
2285 if(duration
!= Aur
->GetAuraMaxDuration())
2287 Aur
->SetAuraMaxDuration(duration
);
2288 Aur
->SetAuraDuration(duration
);
2291 bool added
= unitTarget
->AddAura(Aur
);
2293 // Aura not added and deleted in AddAura call;
2297 // found crash at character loading, broken pointer to Aur...
2298 // Aur was deleted in AddAura()...
2302 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2303 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2304 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2307 void Spell::EffectUnlearnSpecialization( uint32 i
)
2309 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2312 Player
*_player
= (Player
*)unitTarget
;
2313 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2315 _player
->removeSpell(spellToUnlearn
);
2317 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2320 void Spell::EffectPowerDrain(uint32 i
)
2322 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2325 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2329 if(!unitTarget
->isAlive())
2331 if(unitTarget
->getPowerType() != drain_power
)
2336 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2338 //add spell damage bonus
2339 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2341 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2342 uint32 power
= damage
;
2343 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2344 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2347 if(curPower
< power
)
2348 new_damage
= curPower
;
2352 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2354 // Don`t restore from self drain
2355 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2357 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2358 if(manaMultiplier
==0)
2361 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2362 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2364 int32 gain
= int32(new_damage
*manaMultiplier
);
2366 m_caster
->ModifyPower(POWER_MANA
,gain
);
2368 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2372 void Spell::EffectSendEvent(uint32 EffectIndex
)
2375 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2377 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2378 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2381 void Spell::EffectPowerBurn(uint32 i
)
2383 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2386 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2390 if(!unitTarget
->isAlive())
2392 if(unitTarget
->getPowerType()!=powertype
)
2397 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2399 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2400 uint32 power
= damage
;
2401 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2402 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2404 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2406 unitTarget
->ModifyPower(powertype
,-new_damage
);
2407 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2409 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2410 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2412 new_damage
= int32(new_damage
*multiplier
);
2413 m_damage
+=new_damage
;
2416 void Spell::EffectHeal( uint32
/*i*/ )
2418 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2420 // Try to get original caster
2421 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2423 // Skip if m_originalCaster not available
2427 int32 addhealth
= damage
;
2429 // Vessel of the Naaru (Vial of the Sunwell trinket)
2430 if (m_spellInfo
->Id
== 45064)
2432 // Amount of heal - depends from stacked Holy Energy
2433 int damageAmount
= 0;
2434 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2435 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2436 if((*i
)->GetId() == 45062)
2437 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2439 m_caster
->RemoveAurasDueToSpell(45062);
2441 addhealth
+= damageAmount
;
2443 // Swiftmend - consumes Regrowth or Rejuvenation
2444 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2446 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2447 // find most short by duration
2448 Aura
*targetAura
= NULL
;
2449 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2451 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2452 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2454 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2461 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2467 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2472 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2473 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2474 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2476 addhealth
+= tickheal
* tickcount
;
2479 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2481 m_healing
+=addhealth
;
2485 void Spell::EffectHealPct( uint32
/*i*/ )
2487 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2489 // Try to get original caster
2490 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2492 // Skip if m_originalCaster not available
2496 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2497 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2499 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2500 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2502 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2503 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2504 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2508 void Spell::EffectHealMechanical( uint32
/*i*/ )
2510 // Mechanic creature type should be correctly checked by targetCreatureType field
2511 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2513 // Try to get original caster
2514 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2516 // Skip if m_originalCaster not available
2520 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2521 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2522 unitTarget
->ModifyHealth( int32(damage
) );
2526 void Spell::EffectHealthLeech(uint32 i
)
2530 if(!unitTarget
->isAlive())
2536 sLog
.outDebug("HealthLeech :%i", damage
);
2538 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2540 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2541 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2543 int32 new_damage
= int32(damage
*multiplier
);
2544 uint32 curHealth
= unitTarget
->GetHealth();
2545 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2546 if(curHealth
< new_damage
)
2547 new_damage
= curHealth
;
2549 if(m_caster
->isAlive())
2551 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2553 m_caster
->ModifyHealth(new_damage
);
2555 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2556 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2558 // m_healthLeech+=tmpvalue;
2559 // m_damage+=new_damage;
2562 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2564 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2567 Player
* player
= (Player
*)unitTarget
;
2569 uint32 newitemid
= itemtype
;
2570 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2573 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2579 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2580 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2582 int32 basePoints
= m_currentBasePoints
[i
];
2583 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2585 num_to_add
= basePoints
+ irand(1, randomPoints
);
2587 num_to_add
= basePoints
+ 1;
2589 else if (pProto
->MaxCount
== 1)
2591 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2593 int32 basePoints
= m_currentBasePoints
[i
];
2594 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2595 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2602 if (num_to_add
> pProto
->GetMaxStackSize())
2603 num_to_add
= pProto
->GetMaxStackSize();
2605 // init items_count to 1, since 1 item will be created regardless of specialization
2607 // the chance to create additional items
2608 float additionalCreateChance
=0.0f
;
2609 // the maximum number of created additional items
2610 uint8 additionalMaxNum
=0;
2611 // get the chance and maximum number for creating extra items
2612 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2614 // roll with this chance till we roll not to create or we create the max num
2615 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2619 // really will be created more items
2620 num_to_add
*= items_count
;
2622 // can the player store the new item?
2623 ItemPosCountVec dest
;
2624 uint32 no_space
= 0;
2625 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2626 if( msg
!= EQUIP_ERR_OK
)
2628 // convert to possible store amount
2629 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2630 num_to_add
-= no_space
;
2633 // if not created by another reason from full inventory or unique items amount limitation
2634 player
->SendEquipError( msg
, NULL
, NULL
);
2641 // create the new item and store it
2642 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2644 // was it successful? return error if not
2647 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2651 // set the "Crafted by ..." property of the item
2652 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2653 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2655 // send info to the client
2657 player
->SendNewItem(pItem
, num_to_add
, true, true);
2659 // we succeeded in creating at least one item, so a levelup is possible
2660 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2663 // for battleground marks send by mail if not add all expected
2666 BattleGroundTypeId bgType
;
2667 switch(m_spellInfo
->Id
)
2669 case SPELL_AV_MARK_WINNER
:
2670 case SPELL_AV_MARK_LOSER
:
2671 bgType
= BATTLEGROUND_AV
;
2673 case SPELL_WS_MARK_WINNER
:
2674 case SPELL_WS_MARK_LOSER
:
2675 bgType
= BATTLEGROUND_WS
;
2677 case SPELL_AB_MARK_WINNER
:
2678 case SPELL_AB_MARK_LOSER
:
2679 bgType
= BATTLEGROUND_AB
;
2685 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2686 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2690 void Spell::EffectCreateItem(uint32 i
)
2692 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2695 void Spell::EffectCreateItem2(uint32 i
)
2697 // special case: generate using spell_loot_template
2698 if(!m_spellInfo
->EffectItemType
[i
])
2700 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2703 // create some random items
2704 ((Player
*)m_caster
)->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
2707 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2710 void Spell::EffectPersistentAA(uint32 i
)
2712 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2714 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2715 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2717 int32 duration
= GetSpellDuration(m_spellInfo
);
2718 DynamicObject
* dynObj
= new DynamicObject
;
2719 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
))
2724 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2725 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2726 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2727 m_caster
->AddDynObject(dynObj
);
2728 dynObj
->GetMap()->Add(dynObj
);
2731 void Spell::EffectEnergize(uint32 i
)
2735 if(!unitTarget
->isAlive())
2738 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2741 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2743 // Some level depends spells
2746 switch (m_spellInfo
->Id
)
2750 level_diff
= m_caster
->getLevel() - 40;
2755 level_diff
= m_caster
->getLevel() - 60;
2760 level_diff
= m_caster
->getLevel() - 60;
2768 damage
-= multiplier
* level_diff
;
2773 if(unitTarget
->GetMaxPower(power
) == 0)
2776 unitTarget
->ModifyPower(power
,damage
);
2777 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2779 // Mad Alchemist's Potion
2780 if (m_spellInfo
->Id
== 45051)
2782 // find elixirs on target
2783 uint32 elixir_mask
= 0;
2784 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2785 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2787 uint32 spell_id
= itr
->second
->GetId();
2788 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2789 elixir_mask
|= mask
;
2792 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2793 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2795 // get all available elixirs by mask and spell level
2796 std::vector
<uint32
> elixirs
;
2797 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2798 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2800 if (itr
->second
& elixir_mask
)
2802 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2805 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2806 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2809 elixirs
.push_back(itr
->first
);
2813 if (!elixirs
.empty())
2815 // cast random elixir on target
2816 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2817 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2822 void Spell::EffectEnergisePct(uint32 i
)
2826 if(!unitTarget
->isAlive())
2829 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2832 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2834 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2838 uint32 gain
= damage
* maxPower
/ 100;
2839 unitTarget
->ModifyPower(power
, gain
);
2840 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2843 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2845 Player
* player
= (Player
*)m_caster
;
2851 if (Script
->GOHello(player
, gameObjTarget
))
2854 switch (gameObjTarget
->GetGoType())
2856 case GAMEOBJECT_TYPE_DOOR
:
2857 case GAMEOBJECT_TYPE_BUTTON
:
2858 gameObjTarget
->UseDoorOrButton();
2859 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2862 case GAMEOBJECT_TYPE_QUESTGIVER
:
2863 // start or end quest
2864 player
->PrepareQuestMenu(guid
);
2865 player
->SendPreparedQuest(guid
);
2868 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2869 // triggering linked GO
2870 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2871 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2874 case GAMEOBJECT_TYPE_GOOBER
:
2875 // goober_scripts can be triggered if the player don't have the quest
2876 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2878 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2879 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2882 // cast goober spell
2883 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2884 ///Quest require to be active for GO using
2885 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2888 gameObjTarget
->AddUniqueUse(player
);
2889 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2891 //TODO? Objective counting called without spell check but with quest objective check
2892 // if send spell id then this line will duplicate to spell casting call (double counting)
2893 // So we or have this line and not required in quest_template have reqSpellIdN
2894 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2895 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2897 // triggering linked GO
2898 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2899 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2903 case GAMEOBJECT_TYPE_CHEST
:
2904 // TODO: possible must be moved to loot release (in different from linked triggering)
2905 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2907 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2908 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2911 // triggering linked GO
2912 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2913 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2915 // Don't return, let loots been taken
2920 player
->SendLoot(guid
, loottype
);
2923 void Spell::EffectOpenLock(uint32 effIndex
)
2925 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2927 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2931 Player
* player
= (Player
*)m_caster
;
2939 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2940 // Arathi Basin banner opening !
2941 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2942 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2944 //CanUseBattleGroundObject() already called in CheckCast()
2945 // in battleground check
2946 if(BattleGround
*bg
= player
->GetBattleGround())
2948 // check if it's correct bg
2949 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2950 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2954 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2956 //CanUseBattleGroundObject() already called in CheckCast()
2957 // in battleground check
2958 if(BattleGround
*bg
= player
->GetBattleGround())
2960 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2961 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2965 lockId
= gameObjTarget
->GetLockId();
2966 guid
= gameObjTarget
->GetGUID();
2970 lockId
= itemTarget
->GetProto()->LockID
;
2971 guid
= itemTarget
->GetGUID();
2975 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2979 SkillType skillId
= SKILL_NONE
;
2980 int32 reqSkillValue
= 0;
2983 SpellCastResult res
= CanOpenLock(effIndex
,lockId
,skillId
,reqSkillValue
,skillValue
);
2984 if(res
!= SPELL_CAST_OK
)
2986 SendCastResult(res
);
2990 SendLoot(guid
, LOOT_SKINNING
);
2992 // not allow use skill grow at item base open
2993 if(!m_CastItem
&& skillId
!= SKILL_NONE
)
2995 // update skill if really known
2996 if(uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3000 // Allow one skill-up until respawned
3001 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3002 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
) )
3003 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3008 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3014 void Spell::EffectSummonChangeItem(uint32 i
)
3016 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3019 Player
*player
= (Player
*)m_caster
;
3021 // applied only to using item
3025 // ... only to item in own inventory/bank/equip_slot
3026 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3029 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3033 uint16 pos
= m_CastItem
->GetPos();
3035 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3039 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3041 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3042 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3045 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3047 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3048 player
->DurabilityLoss(pNewItem
, loosePercent
);
3051 if( player
->IsInventoryPos( pos
) )
3053 ItemPosCountVec dest
;
3054 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3055 if( msg
== EQUIP_ERR_OK
)
3057 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3059 // prevent crash at access and unexpected charges counting with item update queue corrupt
3060 if(m_CastItem
==m_targets
.getItemTarget())
3061 m_targets
.setItemTarget(NULL
);
3065 player
->StoreItem( dest
, pNewItem
, true);
3069 else if( player
->IsBankPos ( pos
) )
3071 ItemPosCountVec dest
;
3072 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3073 if( msg
== EQUIP_ERR_OK
)
3075 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3077 // prevent crash at access and unexpected charges counting with item update queue corrupt
3078 if(m_CastItem
==m_targets
.getItemTarget())
3079 m_targets
.setItemTarget(NULL
);
3083 player
->BankItem( dest
, pNewItem
, true);
3087 else if( player
->IsEquipmentPos ( pos
) )
3090 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3091 if( msg
== EQUIP_ERR_OK
)
3093 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3095 // prevent crash at access and unexpected charges counting with item update queue corrupt
3096 if(m_CastItem
==m_targets
.getItemTarget())
3097 m_targets
.setItemTarget(NULL
);
3101 player
->EquipItem( dest
, pNewItem
, true);
3102 player
->AutoUnequipOffhandIfNeed();
3111 void Spell::EffectOpenSecretSafe(uint32 i
)
3113 EffectOpenLock(i
); //no difference for now
3116 void Spell::EffectProficiency(uint32
/*i*/)
3118 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3120 Player
*p_target
= (Player
*)unitTarget
;
3122 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3123 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3125 p_target
->AddWeaponProficiency(subClassMask
);
3126 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3128 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3130 p_target
->AddArmorProficiency(subClassMask
);
3131 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3135 void Spell::EffectApplyAreaAura(uint32 i
)
3139 if(!unitTarget
->isAlive())
3142 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3143 unitTarget
->AddAura(Aur
);
3146 void Spell::EffectSummonType(uint32 i
)
3148 switch(m_spellInfo
->EffectMiscValueB
[i
])
3150 case SUMMON_TYPE_GUARDIAN
:
3151 case SUMMON_TYPE_POSESSED
:
3152 case SUMMON_TYPE_POSESSED2
:
3153 case SUMMON_TYPE_FORCE_OF_NATURE
:
3154 case SUMMON_TYPE_GUARDIAN2
:
3155 EffectSummonGuardian(i
);
3157 case SUMMON_TYPE_WILD
:
3158 EffectSummonWild(i
);
3160 case SUMMON_TYPE_DEMON
:
3161 EffectSummonDemon(i
);
3163 case SUMMON_TYPE_SUMMON
:
3166 case SUMMON_TYPE_CRITTER
:
3167 case SUMMON_TYPE_CRITTER2
:
3168 case SUMMON_TYPE_CRITTER3
:
3169 EffectSummonCritter(i
);
3171 case SUMMON_TYPE_TOTEM_SLOT1
:
3172 case SUMMON_TYPE_TOTEM_SLOT2
:
3173 case SUMMON_TYPE_TOTEM_SLOT3
:
3174 case SUMMON_TYPE_TOTEM_SLOT4
:
3175 case SUMMON_TYPE_TOTEM
:
3176 EffectSummonTotem(i
);
3178 case SUMMON_TYPE_UNKNOWN1
:
3179 case SUMMON_TYPE_UNKNOWN2
:
3180 case SUMMON_TYPE_UNKNOWN3
:
3181 case SUMMON_TYPE_UNKNOWN4
:
3182 case SUMMON_TYPE_UNKNOWN5
:
3185 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3190 void Spell::EffectSummon(uint32 i
)
3192 if(m_caster
->GetPetGUID())
3197 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3200 uint32 level
= m_caster
->getLevel();
3201 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3203 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3205 // set timer for unsummon
3206 int32 duration
= GetSpellDuration(m_spellInfo
);
3208 spawnCreature
->SetDuration(duration
);
3213 Map
*map
= m_caster
->GetMap();
3214 uint32 pet_number
= objmgr
.GeneratePetNumber();
3215 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_caster
->GetPhaseMask(),
3216 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3218 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3219 delete spawnCreature
;
3223 // Summon in dest location
3225 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3227 x
= m_targets
.m_destX
;
3228 y
= m_targets
.m_destY
;
3229 z
= m_targets
.m_destZ
;
3232 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3234 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3236 if(!spawnCreature
->IsPositionValid())
3238 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3239 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3240 delete spawnCreature
;
3244 // set timer for unsummon
3245 int32 duration
= GetSpellDuration(m_spellInfo
);
3247 spawnCreature
->SetDuration(duration
);
3249 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3250 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3251 spawnCreature
->setPowerType(POWER_MANA
);
3252 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3253 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3254 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3255 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3256 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3257 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3258 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3259 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3260 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3262 spawnCreature
->InitStatsForLevel(level
);
3264 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3266 spawnCreature
->AIM_Initialize();
3267 spawnCreature
->InitPetCreateSpells();
3268 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3269 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3271 std::string name
= m_caster
->GetName();
3272 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3273 spawnCreature
->SetName( name
);
3275 map
->Add((Creature
*)spawnCreature
);
3277 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3279 m_caster
->SetPet(spawnCreature
);
3280 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3281 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3282 ((Player
*)m_caster
)->PetSpellInitialize();
3286 void Spell::EffectLearnSpell(uint32 i
)
3291 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3293 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3294 EffectLearnPetSpell(i
);
3299 Player
*player
= (Player
*)unitTarget
;
3301 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3302 player
->learnSpell(spellToLearn
,false);
3304 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3307 void Spell::EffectDispel(uint32 i
)
3312 // Fill possible dispell list
3313 std::vector
<Aura
*> dispel_list
;
3315 // Create dispel mask by dispel type
3316 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3317 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3318 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3319 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3321 Aura
*aur
= (*itr
).second
;
3322 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3324 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3326 bool positive
= true;
3327 if (!aur
->IsPositive())
3330 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3332 // do not remove positive auras if friendly target
3333 // negative auras if non-friendly target
3334 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3337 // Add aura to dispel list
3338 dispel_list
.push_back(aur
);
3341 // Ok if exist some buffs for dispel try dispel it
3342 if (!dispel_list
.empty())
3344 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3345 std::list
< uint32
> fail_list
; // spell_id
3346 int32 list_size
= dispel_list
.size();
3347 // Dispell N = damage buffs (or while exist buffs for dispel)
3348 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3350 // Random select buff for dispel
3351 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3353 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3354 // Base dispel chance
3355 // TODO: possible chance depend from spell level??
3356 int32 miss_chance
= 0;
3357 // Apply dispel mod from aura caster
3358 if (Unit
*caster
= aur
->GetCaster())
3360 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3361 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3364 if (roll_chance_i(miss_chance
))
3365 fail_list
.push_back(aur
->GetId());
3367 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3368 // Remove buff from list for prevent doubles
3369 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3371 Aura
*dispeled
= *j
;
3372 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3374 j
= dispel_list
.erase(j
);
3381 // Send success log and really remove auras
3382 if (!success_list
.empty())
3384 int32 count
= success_list
.size();
3385 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3386 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3387 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3388 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3389 data
<< uint8(0); // not used
3390 data
<< uint32(count
); // count
3391 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3393 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3394 data
<< uint32(spellInfo
->Id
); // Spell Id
3395 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3396 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3398 m_caster
->SendMessageToSet(&data
, true);
3402 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3404 uint32 heal_spell
= 0;
3405 switch (m_spellInfo
->Id
)
3407 case 19505: heal_spell
= 19658; break;
3408 case 19731: heal_spell
= 19732; break;
3409 case 19734: heal_spell
= 19733; break;
3410 case 19736: heal_spell
= 19735; break;
3411 case 27276: heal_spell
= 27278; break;
3412 case 27277: heal_spell
= 27279; break;
3414 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3418 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3421 // Send fail log to client
3422 if (!fail_list
.empty())
3424 // Failed to dispell
3425 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3426 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3427 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3428 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3429 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3430 data
<< uint32(*j
); // Spell Id
3431 m_caster
->SendMessageToSet(&data
, true);
3436 void Spell::EffectDualWield(uint32
/*i*/)
3438 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3439 ((Player
*)unitTarget
)->SetCanDualWield(true);
3442 void Spell::EffectPull(uint32
/*i*/)
3444 // TODO: create a proper pull towards distract spell center for distract
3445 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3448 void Spell::EffectDistract(uint32
/*i*/)
3450 // Check for possible target
3451 if (!unitTarget
|| unitTarget
->isInCombat())
3454 // target must be OK to do this
3455 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3458 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3460 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3462 // For players just turn them
3464 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3465 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3466 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3470 // Set creature Distracted, Stop it, And turn it
3471 unitTarget
->SetOrientation(angle
);
3472 unitTarget
->StopMoving();
3473 unitTarget
->GetMotionMaster()->MoveDistract(damage
*IN_MILISECONDS
);
3477 void Spell::EffectPickPocket(uint32
/*i*/)
3479 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3482 // victim must be creature and attackable
3483 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3486 // victim have to be alive and humanoid or undead
3487 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3489 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3491 if (chance
> irand(0, 19))
3493 // Stealing successful
3494 //sLog.outDebug("Sending loot from pickpocket");
3495 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3499 // Reveal action + get attack
3500 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3501 if (((Creature
*)unitTarget
)->AI())
3502 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3507 void Spell::EffectAddFarsight(uint32 i
)
3509 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3510 int32 duration
= GetSpellDuration(m_spellInfo
);
3511 DynamicObject
* dynObj
= new DynamicObject
;
3512 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
))
3517 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3518 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3519 m_caster
->AddDynObject(dynObj
);
3520 dynObj
->GetMap()->Add(dynObj
);
3521 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3522 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3525 void Spell::EffectSummonWild(uint32 i
)
3527 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3531 uint32 level
= m_caster
->getLevel();
3533 // level of creature summoned using engineering item based at engineering skill level
3534 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3536 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3537 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3539 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3547 // select center of summon position
3548 float center_x
= m_targets
.m_destX
;
3549 float center_y
= m_targets
.m_destY
;
3550 float center_z
= m_targets
.m_destZ
;
3552 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3554 int32 amount
= damage
> 0 ? damage
: 1;
3556 for(int32 count
= 0; count
< amount
; ++count
)
3559 // If dest location if present
3560 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3562 // Summon 1 unit in dest location
3565 px
= m_targets
.m_destX
;
3566 py
= m_targets
.m_destY
;
3567 pz
= m_targets
.m_destZ
;
3569 // Summon in random point all other units if location present
3571 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3573 // Summon if dest location not present near caster
3575 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3577 int32 duration
= GetSpellDuration(m_spellInfo
);
3579 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3581 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3585 void Spell::EffectSummonGuardian(uint32 i
)
3587 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3591 // Jewelery statue case (totem like)
3592 if(m_spellInfo
->SpellIconID
==2056)
3594 EffectSummonTotem(i
);
3598 // set timer for unsummon
3599 int32 duration
= GetSpellDuration(m_spellInfo
);
3601 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3602 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3603 // so this code hack in fact
3604 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3605 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3606 return; // find old guardian, ignore summon
3608 // in another case summon new
3609 uint32 level
= m_caster
->getLevel();
3611 // level of pet summoned using engineering item based at engineering skill level
3612 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3614 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3615 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3617 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3625 // select center of summon position
3626 float center_x
= m_targets
.m_destX
;
3627 float center_y
= m_targets
.m_destY
;
3628 float center_z
= m_targets
.m_destZ
;
3630 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3632 int32 amount
= damage
> 0 ? damage
: 1;
3634 for(int32 count
= 0; count
< amount
; ++count
)
3636 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3638 Map
*map
= m_caster
->GetMap();
3639 uint32 pet_number
= objmgr
.GeneratePetNumber();
3640 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3641 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3643 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3644 delete spawnCreature
;
3649 // If dest location if present
3650 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3652 // Summon 1 unit in dest location
3655 px
= m_targets
.m_destX
;
3656 py
= m_targets
.m_destY
;
3657 pz
= m_targets
.m_destZ
;
3659 // Summon in random point all other units if location present
3661 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3663 // Summon if dest location not present near caster
3665 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3667 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3669 if(!spawnCreature
->IsPositionValid())
3671 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3672 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3673 delete spawnCreature
;
3678 spawnCreature
->SetDuration(duration
);
3680 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3681 spawnCreature
->setPowerType(POWER_MANA
);
3682 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3683 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3684 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3685 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3686 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3687 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3688 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3690 spawnCreature
->InitStatsForLevel(level
);
3691 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3693 spawnCreature
->AIM_Initialize();
3695 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3696 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3698 map
->Add((Creature
*)spawnCreature
);
3702 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3707 if(unitTarget
->isInFlight())
3710 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3713 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3715 unitTarget
->NearTeleportTo(fx
,fy
,fz
,-m_caster
->GetOrientation(),unitTarget
==m_caster
);
3718 void Spell::EffectLearnSkill(uint32 i
)
3720 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3726 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3727 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3728 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3731 void Spell::EffectAddHonor(uint32
/*i*/)
3733 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3736 // not scale value for item based reward (/10 value expected)
3739 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/10);
3740 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());
3744 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3747 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
3748 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
3749 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
3753 //maybe we have correct honor_gain in damage already
3754 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3755 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3759 void Spell::EffectTradeSkill(uint32
/*i*/)
3761 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3763 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3764 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3765 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3768 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3770 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3775 Player
* p_caster
= (Player
*)m_caster
;
3777 // not grow at item use at item case
3778 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3780 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3784 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3788 // item can be in trade slot and have owner diff. from caster
3789 Player
* item_owner
= itemTarget
->GetOwner();
3793 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3795 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3796 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3797 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3798 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3801 // remove old enchanting before applying new if equipped
3802 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3804 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3806 // add new enchanting if equipped
3807 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3810 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3812 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3817 Player
* p_caster
= (Player
*)m_caster
;
3819 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3823 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3827 // support only enchantings with add socket in this slot
3829 bool add_socket
= false;
3830 for(int i
= 0; i
< 3; ++i
)
3832 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3840 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.",
3841 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3846 // item can be in trade slot and have owner diff. from caster
3847 Player
* item_owner
= itemTarget
->GetOwner();
3851 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3853 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3854 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3855 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3856 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3859 // remove old enchanting before applying new if equipped
3860 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3862 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3864 // add new enchanting if equipped
3865 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3868 void Spell::EffectEnchantItemTmp(uint32 i
)
3870 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3873 Player
* p_caster
= (Player
*)m_caster
;
3878 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3880 // Shaman Rockbiter Weapon
3881 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3883 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3885 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3886 // with already applied percent bonus from Elemental Weapons talent
3887 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3888 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3889 switch(enchnting_damage
)
3892 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3894 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3895 case 5: enchant_id
= 3025; break; // 20%
3897 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3898 case 7: enchant_id
= 3027; break; // 20%
3900 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3901 case 10: enchant_id
= 503; break; // 14%
3902 case 11: enchant_id
= 3031; break; // 20%
3904 case 15: enchant_id
= 3035; break; // 0%
3905 case 16: enchant_id
= 1663; break; // 7%
3906 case 17: enchant_id
= 3033; break; // 14%
3907 case 18: enchant_id
= 3034; break; // 20%
3909 case 28: enchant_id
= 3038; break; // 0%
3910 case 29: enchant_id
= 683; break; // 7%
3911 case 31: enchant_id
= 3036; break; // 14%
3912 case 33: enchant_id
= 3037; break; // 20%
3914 case 40: enchant_id
= 3041; break; // 0%
3915 case 42: enchant_id
= 1664; break; // 7%
3916 case 45: enchant_id
= 3039; break; // 14%
3917 case 48: enchant_id
= 3040; break; // 20%
3919 case 49: enchant_id
= 3044; break; // 0%
3920 case 52: enchant_id
= 2632; break; // 7%
3921 case 55: enchant_id
= 3042; break; // 14%
3922 case 58: enchant_id
= 3043; break; // 20%
3924 case 62: enchant_id
= 2633; break; // 0%
3925 case 66: enchant_id
= 3018; break; // 7%
3926 case 70: enchant_id
= 3019; break; // 14%
3927 case 74: enchant_id
= 3020; break; // 20%
3929 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3936 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3940 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3943 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3947 // select enchantment duration
3950 // rogue family enchantments exception by duration
3951 if(m_spellInfo
->Id
==38615)
3952 duration
= 1800; // 30 mins
3953 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3954 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3955 duration
= 3600; // 1 hour
3956 // shaman family enchantments
3957 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3958 duration
= 1800; // 30 mins
3959 // other cases with this SpellVisual already selected
3960 else if(m_spellInfo
->SpellVisual
[0]==215)
3961 duration
= 1800; // 30 mins
3962 // some fishing pole bonuses
3963 else if(m_spellInfo
->SpellVisual
[0]==563)
3964 duration
= 600; // 10 mins
3965 // shaman rockbiter enchantments
3966 else if(m_spellInfo
->SpellVisual
[0]==0)
3967 duration
= 1800; // 30 mins
3968 else if(m_spellInfo
->Id
==29702)
3969 duration
= 300; // 5 mins
3970 else if(m_spellInfo
->Id
==37360)
3971 duration
= 300; // 5 mins
3974 duration
= 3600; // 1 hour
3976 // item can be in trade slot and have owner diff. from caster
3977 Player
* item_owner
= itemTarget
->GetOwner();
3981 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3983 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3984 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3985 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3986 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3989 // remove old enchanting before applying new if equipped
3990 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3992 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3994 // add new enchanting if equipped
3995 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3998 void Spell::EffectTameCreature(uint32
/*i*/)
4000 if(m_caster
->GetPetGUID())
4006 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4009 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4011 if(creatureTarget
->isPet())
4014 if(m_caster
->getClass() != CLASS_HUNTER
)
4017 // cast finish successfully
4018 //SendChannelUpdate(0);
4021 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4023 // kill original creature
4024 creatureTarget
->setDeathState(JUST_DIED
);
4025 creatureTarget
->RemoveCorpse();
4026 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4028 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4030 // prepare visual effect for levelup
4031 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4034 pet
->GetMap()->Add((Creature
*)pet
);
4036 // visual effect for levelup
4037 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4039 // caster have pet now
4040 m_caster
->SetPet(pet
);
4042 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4044 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4045 ((Player
*)m_caster
)->PetSpellInitialize();
4049 void Spell::EffectSummonPet(uint32 i
)
4051 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4053 Pet
*OldSummon
= m_caster
->GetPet();
4055 // if pet requested type already exist
4058 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4060 // pet in corpse state can't be summoned
4061 if( OldSummon
->isDead() )
4064 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4065 OldSummon
->SetMapId(m_caster
->GetMapId());
4068 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4070 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4071 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4073 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4075 ((Player
*)m_caster
)->PetSpellInitialize();
4080 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4081 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4086 Pet
* NewSummon
= new Pet
;
4088 // petentry==0 for hunter "call pet" (current pet summoned if any)
4089 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4091 if(NewSummon
->getPetType()==SUMMON_PET
)
4093 // Remove Demonic Sacrifice auras (known pet)
4094 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4095 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4097 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4099 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4100 itr
= auraClassScripts
.begin();
4110 // not error in case fail hunter call pet
4117 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4121 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4126 Map
*map
= m_caster
->GetMap();
4127 uint32 pet_number
= objmgr
.GeneratePetNumber();
4128 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4129 petentry
, pet_number
))
4136 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4138 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4140 if(!NewSummon
->IsPositionValid())
4142 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4143 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4148 uint32 petlevel
= m_caster
->getLevel();
4149 NewSummon
->setPetType(SUMMON_PET
);
4151 uint32 faction
= m_caster
->getFaction();
4152 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4154 if ( ((Creature
*)m_caster
)->isTotem() )
4155 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4157 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4160 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4161 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4162 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4163 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4164 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4165 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4166 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4167 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4168 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4169 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4171 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4172 // this enables pet details window (Shift+P)
4174 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4175 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4176 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4178 NewSummon
->InitStatsForLevel(petlevel
);
4179 NewSummon
->InitPetCreateSpells();
4180 NewSummon
->InitTalentForLevel();
4182 if(NewSummon
->getPetType()==SUMMON_PET
)
4184 // Remove Demonic Sacrifice auras (new pet)
4185 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4186 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4188 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4190 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4191 itr
= auraClassScripts
.begin();
4197 // generate new name for summon pet
4198 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4199 if(!new_name
.empty())
4200 NewSummon
->SetName(new_name
);
4202 else if(NewSummon
->getPetType()==HUNTER_PET
)
4203 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4205 NewSummon
->AIM_Initialize();
4206 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4207 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4209 map
->Add((Creature
*)NewSummon
);
4211 m_caster
->SetPet(NewSummon
);
4212 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4214 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4216 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4217 ((Player
*)m_caster
)->PetSpellInitialize();
4221 void Spell::EffectLearnPetSpell(uint32 i
)
4223 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4226 Player
*_player
= (Player
*)m_caster
;
4228 Pet
*pet
= _player
->GetPet();
4234 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4235 if(!learn_spellproto
)
4238 pet
->learnSpell(learn_spellproto
->Id
);
4240 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4241 _player
->PetSpellInitialize();
4244 void Spell::EffectTaunt(uint32
/*i*/)
4246 // this effect use before aura Taunt apply for prevent taunt already attacking target
4247 // for spell as marked "non effective at already attacking target"
4248 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4250 if(unitTarget
->getVictim()==m_caster
)
4252 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4257 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4258 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4259 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4262 void Spell::EffectWeaponDmg(uint32 i
)
4266 if(!unitTarget
->isAlive())
4269 // multiple weapon dmg effect workaround
4270 // execute only the last weapon damage
4271 // and handle all effects at once
4272 for (int j
= 0; j
< 3; j
++)
4274 switch(m_spellInfo
->Effect
[j
])
4276 case SPELL_EFFECT_WEAPON_DAMAGE
:
4277 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4278 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4279 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4280 if (j
< i
) // we must calculate only at last weapon effect
4286 // some spell specific modifiers
4287 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4289 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4290 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4291 bool normalized
= false;
4293 int32 spell_bonus
= 0; // bonus specific for spell
4294 switch(m_spellInfo
->SpellFamilyName
)
4296 case SPELLFAMILY_WARRIOR
:
4298 // Whirlwind, single only spell with 2 weapon white damage apply if have
4299 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4301 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4302 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4304 // Devastate bonus and sunder armor refresh
4305 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4308 // Need refresh all Sunder Armor auras from this caster
4309 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4310 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4312 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4313 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4314 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4315 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4317 (*itr
).second
->RefreshAura();
4318 stack
= (*itr
).second
->GetStackAmount();
4322 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4326 case SPELLFAMILY_ROGUE
:
4328 // Mutilate (for each hand)
4329 if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4333 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4338 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4339 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4341 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4350 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4354 case SPELLFAMILY_PALADIN
:
4356 // Seal of Command - receive benefit from Spell Damage and Healing
4357 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4359 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4360 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4361 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4365 case SPELLFAMILY_SHAMAN
:
4367 // Skyshatter Harness item set bonus
4369 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4371 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4372 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4374 // Stormstrike AP Buff
4375 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4377 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4385 int32 fixed_bonus
= 0;
4386 for (int j
= 0; j
< 3; j
++)
4388 switch(m_spellInfo
->Effect
[j
])
4390 case SPELL_EFFECT_WEAPON_DAMAGE
:
4391 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4392 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4394 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4395 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4398 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4399 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4401 // applied only to prev.effects fixed damage
4402 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4405 break; // not weapon damage effect, just skip
4409 // apply weaponDamagePercentMod to spell bonus also
4410 if(spellBonusNeedWeaponDamagePercentMod
)
4411 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4413 // non-weapon damage
4414 int32 bonus
= spell_bonus
+ fixed_bonus
;
4416 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4420 switch(m_attackType
)
4423 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4424 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4425 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4428 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4429 bonus
= int32(bonus
*weapon_total_pct
);
4432 // + weapon damage with applied weapon% dmg to base weapon damage in call
4433 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4436 bonus
= int32(bonus
*totalDamagePercentMod
);
4438 // prevent negative damage
4439 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4441 // Add melee damage bonuses (also check for negative)
4442 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4443 m_damage
+= eff_damage
;
4446 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4448 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4449 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4453 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4455 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4456 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4460 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4462 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4464 // wands don't have ammo
4465 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4468 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4470 if(pItem
->GetMaxStackCount()==1)
4472 // decrease durability for non-stackable throw weapon
4473 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4477 // decrease items amount for stackable throw weapon
4479 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4482 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4483 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4487 void Spell::EffectThreat(uint32
/*i*/)
4489 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4492 if(!unitTarget
->CanHaveThreatList())
4495 unitTarget
->AddThreat(m_caster
, float(damage
));
4498 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4502 if(!unitTarget
->isAlive())
4505 uint32 heal
= m_caster
->GetMaxHealth();
4510 void Spell::EffectInterruptCast(uint32
/*i*/)
4514 if(!unitTarget
->isAlive())
4517 // TODO: not all spells that used this effect apply cooldown at school spells
4518 // also exist case: apply cooldown to interrupted cast only and to all spells
4519 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4521 if (unitTarget
->m_currentSpells
[i
])
4523 // check if we can interrupt spell
4524 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4526 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4527 unitTarget
->InterruptSpell(i
,false);
4533 void Spell::EffectSummonObjectWild(uint32 i
)
4535 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4537 GameObject
* pGameObj
= new GameObject
;
4539 WorldObject
* target
= focusObject
;
4544 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4546 x
= m_targets
.m_destX
;
4547 y
= m_targets
.m_destY
;
4548 z
= m_targets
.m_destZ
;
4551 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4553 Map
*map
= target
->GetMap();
4555 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4556 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4562 int32 duration
= GetSpellDuration(m_spellInfo
);
4563 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4564 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4566 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4567 m_caster
->AddGameObject(pGameObj
);
4570 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4572 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4574 Player
*pl
= (Player
*)m_caster
;
4575 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4576 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4578 uint32 team
= ALLIANCE
;
4580 if(pl
->GetTeam() == team
)
4583 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4588 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4590 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4592 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4593 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4595 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4600 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4602 GameObject
* linkedGO
= new GameObject
;
4603 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4604 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4606 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4607 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4609 m_caster
->AddGameObject(linkedGO
);
4621 void Spell::EffectScriptEffect(uint32 effIndex
)
4623 // TODO: we must implement hunter pet summon at login there (spell 6962)
4625 switch(m_spellInfo
->SpellFamilyName
)
4627 case SPELLFAMILY_GENERIC
:
4629 switch(m_spellInfo
->Id
)
4631 // PX-238 Winter Wondervolt TRAP
4634 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4637 for(int j
= 0; j
< 4; ++j
)
4638 if(unitTarget
->HasAura(spells
[j
],0))
4642 uint32 iTmpSpellId
= spells
[urand(0,3)];
4645 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4651 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4654 uint32 spell_id
= 0;
4657 case 1: spell_id
= 8854; break;
4658 default: spell_id
= 8855; break;
4661 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4664 // Brittle Armor - need remove one 24575 Brittle Armor aura
4666 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4668 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4670 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4672 // Orb teleport spells
4686 switch(m_spellInfo
->Id
)
4688 case 25140: spellid
= 32571; break;
4689 case 25143: spellid
= 32572; break;
4690 case 25650: spellid
= 30140; break;
4691 case 25652: spellid
= 30141; break;
4692 case 29128: spellid
= 32568; break;
4693 case 29129: spellid
= 32569; break;
4694 case 35376: spellid
= 25649; break;
4695 case 35727: spellid
= 35730; break;
4700 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4703 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4718 if(!unitTarget
|| !unitTarget
->isAlive())
4721 // Onyxia Scale Cloak
4722 if(unitTarget
->GetDummyAura(22683))
4726 m_caster
->CastSpell(unitTarget
, 22682, true);
4729 // Summon Black Qiraji Battle Tank
4735 // Prevent stacking of mounts
4736 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4738 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4739 if (unitTarget
->GetAreaId() == 3428)
4740 unitTarget
->CastSpell(unitTarget
, 25863, false);
4742 unitTarget
->CastSpell(unitTarget
, 26655, false);
4745 // Piccolo of the Flaming Fire
4748 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4750 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4756 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4757 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4760 // Mirren's Drinking Hat
4764 switch ( urand(1,6) )
4766 case 1:case 2:case 3:
4767 item
= 23584;break; // Loch Modan Lager
4769 item
= 23585;break; // Stouthammer Lite
4771 item
= 23586;break; // Aerie Peak Pale Ale
4774 DoCreateItem(effIndex
,item
);
4780 // Removes snares and roots.
4781 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4782 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4783 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4787 Aura
*aur
= iter
->second
;
4788 if (!aur
->IsPositive()) //only remove negative spells
4790 // check for mechanic mask
4791 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4793 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4797 next
= Auras
.begin();
4809 unitTarget
->CastSpell(unitTarget
, 41131, true);
4812 // Force Cast - Portal Effect: Sunwell Isle
4818 unitTarget
->CastSpell(unitTarget
, 44870, true);
4821 // Goblin Weather Machine
4830 case 0: spellId
= 46740; break;
4831 case 1: spellId
= 46739; break;
4832 case 2: spellId
= 46738; break;
4833 case 3: spellId
= 46736; break;
4835 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4841 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4844 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4848 // Emblazon Runeblade
4854 unitTarget
->CastSpell(unitTarget
,51771,false);
4860 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4862 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4863 unitTarget
->CastSpell(unitTarget
, damage
, false);
4866 case 58418: // Portal to Orgrimmar
4867 case 58420: // Portal to Stormwind
4869 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
4872 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
4873 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
4875 if( ((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
) )
4876 unitTarget
->CastSpell(unitTarget
, spellID
, true);
4880 // random spell learn instead placeholder
4881 case 60893: // Northrend Alchemy Research
4882 case 61177: // Northrend Inscription Research
4883 case 61288: // Minor Inscription Research
4884 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4886 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4888 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4892 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4894 Player
* player
= (Player
*)m_caster
;
4896 // need replace effect 0 item by loot
4897 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4899 if(!player
->HasItemCount(reagent_id
,1))
4904 player
->DestroyItemCount (reagent_id
,count
,true);
4906 // create some random items
4907 player
->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
4909 // learn random explicit discovery recipe (if any)
4910 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4911 player
->learnSpell(discoveredSpell
,false);
4917 case SPELLFAMILY_WARLOCK
:
4919 switch(m_spellInfo
->Id
)
4921 // Healthstone creating spells
4933 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4934 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4936 if((*i
)->GetId() == 18692)
4941 else if((*i
)->GetId() == 18693)
4948 static uint32
const itypes
[8][3] = {
4949 { 5512,19004,19005}, // Minor Healthstone
4950 { 5511,19006,19007}, // Lesser Healthstone
4951 { 5509,19008,19009}, // Healthstone
4952 { 5510,19010,19011}, // Greater Healthstone
4953 { 9421,19012,19013}, // Major Healthstone
4954 {22103,22104,22105}, // Master Healthstone
4955 {36889,36890,36891}, // Demonic Healthstone
4956 {36892,36893,36894} // Fel Healthstone
4959 switch(m_spellInfo
->Id
)
4962 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4964 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4966 itemtype
=itypes
[2][rank
];break; // Healthstone
4968 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4970 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4972 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4974 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4976 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4980 DoCreateItem( effIndex
, itemtype
);
4986 case SPELLFAMILY_PRIEST
:
4988 switch(m_spellInfo
->Id
)
4990 // Pain and Suffering
4995 // Refresh Shadow Word: Pain on target
4996 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
4997 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
4999 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5000 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5001 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
5002 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5004 (*itr
).second
->RefreshAura();
5015 case SPELLFAMILY_HUNTER
:
5017 switch(m_spellInfo
->Id
)
5023 int32 basePoint
= 0;
5024 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5025 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5027 Aura
*aura
= (*i
).second
;
5028 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5030 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5031 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5032 if (!(familyFlag
& 0x000000800000C000LL
))
5034 // Refresh aura duration
5035 aura
->RefreshAura();
5037 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5038 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5040 spellId
= 53353; // 53353 Chimera Shot - Serpent
5041 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5043 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5044 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5046 spellId
= 53358; // 53358 Chimera Shot - Viper
5047 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5049 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5050 if (familyFlag
& 0x0000000000008000LL
)
5051 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5052 // ?? nothing say in spell desc (possibly need addition check)
5053 //if (familyFlag & 0x0000010000000000LL || // dot
5054 // familyFlag & 0x0000100000000000LL) // stun
5056 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5060 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5068 case SPELLFAMILY_PALADIN
:
5071 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5073 if(!unitTarget
|| !unitTarget
->isAlive())
5075 uint32 spellId1
= 0;
5076 uint32 spellId2
= 0;
5078 // Judgement self add switch
5079 switch (m_spellInfo
->Id
)
5081 case 41467: break; // Judgement
5082 case 53407: spellId1
= 20184; break; // Judgement of Justice
5083 case 20271: // Judgement of Light
5084 case 57774: spellId1
= 20185; break; // Judgement of Light
5085 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5089 // all seals have aura dummy in 2 effect
5090 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5091 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5093 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5094 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5095 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5097 spellId2
= (*itr
)->GetModifier()->m_amount
;
5098 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5104 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5106 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5110 case SPELLFAMILY_POTION
:
5112 switch(m_spellInfo
->Id
)
5119 unitTarget
->CastSpell(unitTarget
, 28694, true);
5127 // 25% chance of casting a random buff
5128 if(roll_chance_i(75))
5131 // triggered spells are 28703 to 28707
5132 // Note: some sources say, that there was the possibility of
5133 // receiving a debuff. However, this seems to be removed by a patch.
5134 const uint32 spellid
= 28703;
5136 // don't overwrite an existing aura
5137 for(uint8 i
=0; i
<5; i
++)
5138 if(unitTarget
->HasAura(spellid
+i
, 0))
5140 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5149 // 25% chance of casting Nightmare Pollen
5150 if(roll_chance_i(75))
5152 unitTarget
->CastSpell(unitTarget
, 28721, true);
5160 // normal DB scripted effect
5164 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5165 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5168 void Spell::EffectSanctuary(uint32
/*i*/)
5172 //unitTarget->CombatStop();
5174 unitTarget
->CombatStop();
5175 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5176 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5177 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5179 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5183 void Spell::EffectAddComboPoints(uint32
/*i*/)
5188 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5194 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5197 void Spell::EffectDuel(uint32 i
)
5199 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5202 Player
*caster
= (Player
*)m_caster
;
5203 Player
*target
= (Player
*)unitTarget
;
5205 // caster or target already have requested duel
5206 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5209 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5210 // Don't have to check the target's map since you cannot challenge someone across maps
5211 uint32 mapid
= caster
->GetMapId();
5212 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5214 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5218 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5219 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5221 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5225 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5226 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5228 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5232 //CREATE DUEL FLAG OBJECT
5233 GameObject
* pGameObj
= new GameObject
;
5235 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5237 Map
*map
= m_caster
->GetMap();
5238 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5239 map
, m_caster
->GetPhaseMask(),
5240 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5241 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5242 m_caster
->GetPositionZ(),
5243 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5249 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5250 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5251 int32 duration
= GetSpellDuration(m_spellInfo
);
5252 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5253 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5255 m_caster
->AddGameObject(pGameObj
);
5260 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5261 data
<< pGameObj
->GetGUID();
5262 data
<< caster
->GetGUID();
5263 caster
->GetSession()->SendPacket(&data
);
5264 target
->GetSession()->SendPacket(&data
);
5267 DuelInfo
*duel
= new DuelInfo
;
5268 duel
->initiator
= caster
;
5269 duel
->opponent
= target
;
5270 duel
->startTime
= 0;
5271 duel
->startTimer
= 0;
5272 caster
->duel
= duel
;
5274 DuelInfo
*duel2
= new DuelInfo
;
5275 duel2
->initiator
= caster
;
5276 duel2
->opponent
= caster
;
5277 duel2
->startTime
= 0;
5278 duel2
->startTimer
= 0;
5279 target
->duel
= duel2
;
5281 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5282 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5285 void Spell::EffectStuck(uint32
/*i*/)
5287 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5290 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5293 Player
* pTarget
= (Player
*)unitTarget
;
5295 sLog
.outDebug("Spell Effect: Stuck");
5296 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());
5298 if(pTarget
->isInFlight())
5301 // homebind location is loaded always
5302 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5304 // Stuck spell trigger Hearthstone cooldown
5305 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5308 Spell
spell(pTarget
,spellInfo
,true,0);
5309 spell
.SendSpellCooldown();
5312 void Spell::EffectSummonPlayer(uint32
/*i*/)
5314 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5317 // Evil Twin (ignore player summon, but hide this for summoner)
5318 if(unitTarget
->GetDummyAura(23445))
5322 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5324 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5326 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5327 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5328 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5329 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5330 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5333 static ScriptInfo
generateActivateCommand()
5336 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5340 void Spell::EffectActivateObject(uint32 effect_idx
)
5345 static ScriptInfo activateCommand
= generateActivateCommand();
5347 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5349 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5352 void Spell::EffectApplyGlyph(uint32 i
)
5354 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5357 Player
*player
= (Player
*)m_caster
;
5360 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5362 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5364 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5366 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5368 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5369 return; // glyph slot mismatch
5374 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5376 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5378 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5379 player
->SetGlyph(m_glyphIndex
, 0);
5383 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5384 player
->SetGlyph(m_glyphIndex
, glyph
);
5389 void Spell::EffectSummonTotem(uint32 i
)
5392 switch(m_spellInfo
->EffectMiscValueB
[i
])
5394 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5395 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5396 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5397 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5398 // Battle standard case
5399 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5400 // jewelery statue case, like totem without slot
5401 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5405 if(slot
< MAX_TOTEM
)
5407 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5410 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5411 if(OldTotem
&& OldTotem
->isTotem())
5412 ((Totem
*)OldTotem
)->UnSummon();
5417 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5418 team
= ((Player
*)m_caster
)->GetTeam();
5420 Totem
* pTotem
= new Totem
;
5422 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5423 m_spellInfo
->EffectMiscValue
[i
], team
))
5429 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5432 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5434 // totem must be at same Z in case swimming caster and etc.
5435 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5436 z
= m_caster
->GetPositionZ();
5438 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5440 if(slot
< MAX_TOTEM
)
5441 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5443 pTotem
->SetOwner(m_caster
->GetGUID());
5444 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5446 int32 duration
=GetSpellDuration(m_spellInfo
);
5447 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5448 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5449 pTotem
->SetDuration(duration
);
5451 if (damage
) // if not spell info, DB values used
5453 pTotem
->SetMaxHealth(damage
);
5454 pTotem
->SetHealth(damage
);
5457 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5459 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5460 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5462 pTotem
->Summon(m_caster
);
5464 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5466 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5467 data
<< uint8(slot
);
5468 data
<< uint64(pTotem
->GetGUID());
5469 data
<< uint32(duration
);
5470 data
<< uint32(m_spellInfo
->Id
);
5471 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5475 void Spell::EffectEnchantHeldItem(uint32 i
)
5477 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5478 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5481 Player
* item_owner
= (Player
*)unitTarget
;
5482 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5488 if(!item
->IsEquipped())
5491 if (m_spellInfo
->EffectMiscValue
[i
])
5493 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5494 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5496 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5498 duration
= 10; //10 seconds for enchants which don't have listed duration
5500 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5504 // Always go to temp enchantment slot
5505 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5507 // Enchantment will not be applied if a different one already exists
5508 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5511 // Apply the temporary enchantment
5512 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
5513 item_owner
->ApplyEnchantment(item
,slot
,true);
5517 void Spell::EffectDisEnchant(uint32
/*i*/)
5519 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5522 Player
* p_caster
= (Player
*)m_caster
;
5523 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5526 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5528 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5530 // item will be removed at disenchanting end
5533 void Spell::EffectInebriate(uint32
/*i*/)
5535 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5538 Player
*player
= (Player
*)unitTarget
;
5539 uint16 currentDrunk
= player
->GetDrunkValue();
5540 uint16 drunkMod
= damage
* 256;
5541 if (currentDrunk
+ drunkMod
> 0xFFFF)
5542 currentDrunk
= 0xFFFF;
5544 currentDrunk
+= drunkMod
;
5545 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5548 void Spell::EffectFeedPet(uint32 i
)
5550 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5553 Player
*_player
= (Player
*)m_caster
;
5555 Item
* foodItem
= m_targets
.getItemTarget();
5559 Pet
*pet
= _player
->GetPet();
5566 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5571 _player
->DestroyItemCount(foodItem
,count
,true);
5572 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5574 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5577 void Spell::EffectDismissPet(uint32
/*i*/)
5579 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5582 Pet
* pet
= m_caster
->GetPet();
5584 // not let dismiss dead pet
5585 if(!pet
||!pet
->isAlive())
5588 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5591 void Spell::EffectSummonObject(uint32 i
)
5593 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5596 switch(m_spellInfo
->Effect
[i
])
5598 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5599 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5600 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5601 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5605 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5608 GameObject
* obj
= NULL
;
5610 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5612 if(obj
) obj
->Delete();
5613 m_caster
->m_ObjectSlot
[slot
] = 0;
5616 GameObject
* pGameObj
= new GameObject
;
5619 // If dest location if present
5620 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5622 x
= m_targets
.m_destX
;
5623 y
= m_targets
.m_destY
;
5624 z
= m_targets
.m_destZ
;
5626 // Summon in random point all other units if location present
5628 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5630 Map
*map
= m_caster
->GetMap();
5631 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5632 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5638 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5639 int32 duration
= GetSpellDuration(m_spellInfo
);
5640 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5641 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5642 m_caster
->AddGameObject(pGameObj
);
5645 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5646 data
<< pGameObj
->GetGUID();
5647 m_caster
->SendMessageToSet(&data
,true);
5649 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5652 void Spell::EffectResurrect(uint32
/*effIndex*/)
5656 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5659 if(unitTarget
->isAlive())
5661 if(!unitTarget
->IsInWorld())
5664 switch (m_spellInfo
->Id
)
5666 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5668 if (roll_chance_i(67))
5670 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5674 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5676 if (roll_chance_i(50))
5678 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5686 Player
* pTarget
= ((Player
*)unitTarget
);
5688 if(pTarget
->isRessurectRequested()) // already have one active request
5691 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5692 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5694 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5695 SendResurrectRequest(pTarget
);
5698 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5700 if(!unitTarget
|| !unitTarget
->isAlive())
5703 if( unitTarget
->m_extraAttacks
)
5706 unitTarget
->m_extraAttacks
= damage
;
5709 void Spell::EffectParry(uint32
/*i*/)
5711 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5712 ((Player
*)unitTarget
)->SetCanParry(true);
5715 void Spell::EffectBlock(uint32
/*i*/)
5717 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5718 ((Player
*)unitTarget
)->SetCanBlock(true);
5721 void Spell::EffectMomentMove(uint32 i
)
5723 if(unitTarget
->isInFlight())
5726 if( m_spellInfo
->rangeIndex
== 1) //self range
5728 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5732 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5734 unitTarget
->GetPosition(ox
,oy
,oz
);
5736 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5737 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5742 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5745 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(),unitTarget
==m_caster
);
5749 void Spell::EffectReputation(uint32 i
)
5751 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5754 Player
*_player
= (Player
*)unitTarget
;
5756 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5758 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5760 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5765 _player
->GetReputationMgr().ModifyReputation(factionEntry
,rep_change
);
5768 void Spell::EffectQuestComplete(uint32 i
)
5770 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5773 Player
*_player
= (Player
*)m_caster
;
5775 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5776 _player
->AreaExploredOrEventHappens(quest_id
);
5779 void Spell::EffectSelfResurrect(uint32 i
)
5781 if(!unitTarget
|| unitTarget
->isAlive())
5783 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5785 if(!unitTarget
->IsInWorld())
5794 health
= uint32(-damage
);
5795 mana
= m_spellInfo
->EffectMiscValue
[i
];
5800 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5801 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5802 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5805 Player
*plr
= ((Player
*)unitTarget
);
5806 plr
->ResurrectPlayer(0.0f
);
5808 plr
->SetHealth( health
);
5809 plr
->SetPower(POWER_MANA
, mana
);
5810 plr
->SetPower(POWER_RAGE
, 0 );
5811 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5813 plr
->SpawnCorpseBones();
5818 void Spell::EffectSkinning(uint32
/*i*/)
5820 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5822 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5825 Creature
* creature
= (Creature
*) unitTarget
;
5826 int32 targetLevel
= creature
->getLevel();
5828 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5830 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5831 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5833 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5835 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5837 // Double chances for elites
5838 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5841 void Spell::EffectCharge(uint32
/*i*/)
5843 if(!unitTarget
|| !m_caster
)
5847 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5848 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5849 ((Creature
*)unitTarget
)->StopMoving();
5851 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5852 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5854 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5855 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5857 // not all charge effects used in negative spells
5858 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5859 m_caster
->Attack(unitTarget
,true);
5862 void Spell::EffectSummonCritter(uint32 i
)
5864 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5866 Player
* player
= (Player
*)m_caster
;
5868 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5872 Pet
* old_critter
= player
->GetMiniPet();
5874 // for same pet just despawn
5875 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5877 player
->RemoveMiniPet();
5881 // despawn old pet before summon new
5883 player
->RemoveMiniPet();
5886 Pet
* critter
= new Pet(MINI_PET
);
5888 Map
*map
= m_caster
->GetMap();
5889 uint32 pet_number
= objmgr
.GeneratePetNumber();
5890 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5891 pet_entry
, pet_number
))
5893 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5899 // If dest location if present
5900 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5902 x
= m_targets
.m_destX
;
5903 y
= m_targets
.m_destY
;
5904 z
= m_targets
.m_destZ
;
5906 // Summon if dest location not present near caster
5908 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5910 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5912 if(!critter
->IsPositionValid())
5914 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5915 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5920 critter
->SetOwnerGUID(m_caster
->GetGUID());
5921 critter
->SetCreatorGUID(m_caster
->GetGUID());
5922 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5923 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5925 critter
->AIM_Initialize();
5926 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5927 critter
->SetMaxHealth(1);
5928 critter
->SetHealth(1);
5929 critter
->SetLevel(1);
5931 // set timer for unsummon
5932 int32 duration
= GetSpellDuration(m_spellInfo
);
5934 critter
->SetDuration(duration
);
5936 std::string name
= player
->GetName();
5937 name
.append(petTypeSuffix
[critter
->getPetType()]);
5938 critter
->SetName( name
);
5939 player
->SetMiniPet(critter
);
5941 map
->Add((Creature
*)critter
);
5944 void Spell::EffectKnockBack(uint32 i
)
5946 if(!unitTarget
|| !m_caster
)
5949 // Effect only works on players
5950 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5953 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5954 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5956 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5957 data
.append(unitTarget
->GetPackGUID());
5958 data
<< uint32(0); // Sequence
5959 data
<< float(vcos
); // x direction
5960 data
<< float(vsin
); // y direction
5961 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5962 data
<< float(damage
/-10); // Z Movement speed (vertical)
5964 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5967 void Spell::EffectSendTaxi(uint32 i
)
5969 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5972 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5976 std::vector
<uint32
> nodes
;
5979 nodes
[0] = entry
->from
;
5980 nodes
[1] = entry
->to
;
5983 switch(m_spellInfo
->Id
)
5985 case 31606: //Stormcrow Amulet
5988 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5989 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5990 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5993 case 34905: //Stealth Flight
5996 case 45883: //Amber Ledge to Beryl Point
5999 case 46064: //Amber Ledge to Coldarra
6002 case 53335: //Stormwind Harbor Flight - Peaceful
6007 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
6011 void Spell::EffectPlayerPull(uint32 i
)
6013 if(!unitTarget
|| !m_caster
)
6016 // Effect only works on players
6017 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6020 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6021 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6023 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
6024 data
.append(unitTarget
->GetPackGUID());
6025 data
<< uint32(0); // Sequence
6026 data
<< float(vcos
); // x direction
6027 data
<< float(vsin
); // y direction
6029 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6030 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6032 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6035 void Spell::EffectDispelMechanic(uint32 i
)
6040 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6042 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6043 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6047 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6048 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6050 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6054 next
= Auras
.begin();
6060 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6062 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6064 Player
*_player
= (Player
*)m_caster
;
6065 Pet
*pet
= _player
->GetPet();
6072 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6073 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6074 pet
->setDeathState( ALIVE
);
6075 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6076 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6078 pet
->AIM_Initialize();
6080 _player
->PetSpellInitialize();
6081 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6084 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6087 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6089 if(!m_caster
->m_TotemSlot
[slot
])
6092 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6093 if(totem
&& totem
->isTotem())
6095 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6096 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6098 mana
+= spellInfo
->manaCost
* damage
/ 100;
6099 ((Totem
*)totem
)->UnSummon();
6103 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6104 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6107 void Spell::EffectDurabilityDamage(uint32 i
)
6109 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6112 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6114 // FIXME: some spells effects have value -1/-2
6115 // Possibly its mean -1 all player equipped items and -2 all items
6118 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6122 // invalid slot value
6123 if(slot
>= INVENTORY_SLOT_BAG_END
)
6126 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6127 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6130 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6132 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6135 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6137 // FIXME: some spells effects have value -1/-2
6138 // Possibly its mean -1 all player equipped items and -2 all items
6141 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6145 // invalid slot value
6146 if(slot
>= INVENTORY_SLOT_BAG_END
)
6152 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6153 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6156 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6161 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6164 void Spell::EffectTransmitted(uint32 effIndex
)
6166 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6168 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6172 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6178 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6180 fx
= m_targets
.m_destX
;
6181 fy
= m_targets
.m_destY
;
6182 fz
= m_targets
.m_destZ
;
6184 //FIXME: this can be better check for most objects but still hack
6185 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6187 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6188 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6192 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6193 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6194 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6196 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6199 Map
*cMap
= m_caster
->GetMap();
6201 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6203 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6204 { // but this is not proper, we really need to ignore not materialized objects
6205 SendCastResult(SPELL_FAILED_NOT_HERE
);
6206 SendChannelUpdate(0);
6210 // replace by water level in this case
6211 fz
= cMap
->GetWaterLevel(fx
,fy
);
6213 // if gameobject is summoning object, it should be spawned right on caster's position
6214 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6216 m_caster
->GetPosition(fx
,fy
,fz
);
6219 GameObject
* pGameObj
= new GameObject
;
6221 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6222 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6228 int32 duration
= GetSpellDuration(m_spellInfo
);
6230 switch(goinfo
->type
)
6232 case GAMEOBJECT_TYPE_FISHINGNODE
:
6234 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6235 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6237 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6238 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6242 case 0: lastSec
= 3; break;
6243 case 1: lastSec
= 7; break;
6244 case 2: lastSec
= 13; break;
6245 case 3: lastSec
= 17; break;
6248 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6251 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6253 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6255 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6256 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6260 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6261 case GAMEOBJECT_TYPE_CHEST
:
6268 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6270 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6272 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6273 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6275 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6276 //m_caster->AddGameObject(pGameObj);
6277 //m_ObjToDel.push_back(pGameObj);
6279 cMap
->Add(pGameObj
);
6281 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6282 data
<< uint64(pGameObj
->GetGUID());
6283 m_caster
->SendMessageToSet(&data
,true);
6285 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6287 GameObject
* linkedGO
= new GameObject
;
6288 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6289 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6291 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6292 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6293 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6294 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6296 linkedGO
->GetMap()->Add(linkedGO
);
6307 void Spell::EffectProspecting(uint32
/*i*/)
6309 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6312 Player
* p_caster
= (Player
*)m_caster
;
6313 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6316 if(itemTarget
->GetCount() < 5)
6319 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6321 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6322 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6323 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6326 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6329 void Spell::EffectMilling(uint32
/*i*/)
6331 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6334 Player
* p_caster
= (Player
*)m_caster
;
6335 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6338 if(itemTarget
->GetCount() < 5)
6341 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6343 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6344 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6345 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6348 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6351 void Spell::EffectSkill(uint32
/*i*/)
6353 sLog
.outDebug("WORLD: SkillEFFECT");
6356 void Spell::EffectSummonDemon(uint32 i
)
6358 // select center of summon position
6359 float center_x
= m_targets
.m_destX
;
6360 float center_y
= m_targets
.m_destY
;
6361 float center_z
= m_targets
.m_destZ
;
6363 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6365 int32 amount
= damage
> 0 ? damage
: 1;
6367 for(int32 count
= 0; count
< amount
; ++count
)
6370 // If dest location if present
6371 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6373 // Summon 1 unit in dest location
6376 px
= m_targets
.m_destX
;
6377 py
= m_targets
.m_destY
;
6378 pz
= m_targets
.m_destZ
;
6380 // Summon in random point all other units if location present
6382 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
6384 // Summon if dest location not present near caster
6386 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
6388 int32 duration
= GetSpellDuration(m_spellInfo
);
6390 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,duration
);
6391 if (!Charmed
) // something fatal, not attempt more
6394 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6395 Charmed
->SetLevel(m_caster
->getLevel());
6397 // TODO: Add damage/mana/hp according to level
6399 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6401 // Enslave demon effect, without mana cost and cooldown
6402 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6405 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6410 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6411 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6412 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6413 This is why we use a half sec delay between the visual effect and the resurrection itself */
6414 void Spell::EffectSpiritHeal(uint32
/*i*/)
6417 if(!unitTarget || unitTarget->isAlive())
6419 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6421 if(!unitTarget->IsInWorld())
6424 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6425 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6426 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6427 ((Player*)unitTarget)->SpawnCorpseBones();
6431 // remove insignia spell effect
6432 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6434 sLog
.outDebug("Effect: SkinPlayerCorpse");
6435 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6438 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6441 void Spell::EffectStealBeneficialBuff(uint32 i
)
6443 sLog
.outDebug("Effect: StealBeneficialBuff");
6445 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6448 std::vector
<Aura
*> steal_list
;
6449 // Create dispel mask by dispel type
6450 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6451 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6452 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6454 Aura
*aur
= (*itr
).second
;
6455 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6457 // Need check for passive? this
6458 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6459 steal_list
.push_back(aur
);
6462 // Ok if exist some buffs for dispel try dispel it
6463 if (!steal_list
.empty())
6465 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6466 int32 list_size
= steal_list
.size();
6467 // Dispell N = damage buffs (or while exist buffs for dispel)
6468 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6470 // Random select buff for dispel
6471 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6472 // Not use chance for steal
6473 // TODO possible need do it
6474 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6476 // Remove buff from list for prevent doubles
6477 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6480 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6482 j
= steal_list
.erase(j
);
6489 // Really try steal and send log
6490 if (!success_list
.empty())
6492 int32 count
= success_list
.size();
6493 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6494 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6495 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6496 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6497 data
<< uint8(0); // not used
6498 data
<< uint32(count
); // count
6499 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6501 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6502 data
<< uint32(spellInfo
->Id
); // Spell Id
6503 data
<< uint8(0); // 0 - steals !=0 transfers
6504 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6506 m_caster
->SendMessageToSet(&data
, true);
6511 void Spell::EffectKillCredit(uint32 i
)
6513 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6516 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6519 void Spell::EffectQuestFail(uint32 i
)
6521 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6524 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6527 void Spell::EffectActivateRune(uint32 eff_idx
)
6529 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6532 Player
*plr
= (Player
*)m_caster
;
6534 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6537 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6539 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6541 plr
->SetRuneCooldown(j
, 0);
6546 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6548 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6549 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6552 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6554 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6555 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6558 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);