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
&& m_spellInfo
->Category
==1209)
374 damage
+= int32(m_caster
->GetShieldBlockValue());
376 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
378 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
379 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
383 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
386 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
390 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
392 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
397 case SPELLFAMILY_WARLOCK
:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
404 damage
+= int32(damage
*0.25f
);
408 case SPELLFAMILY_PRIEST
:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
412 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
415 case SPELLFAMILY_DRUID
:
418 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
422 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
423 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
424 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
425 m_caster
->SetPower(POWER_ENERGY
,0);
428 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
430 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
433 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
435 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
439 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
441 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
442 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
443 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
445 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
451 case SPELLFAMILY_ROGUE
:
454 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
462 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
463 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
464 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
465 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
470 // count consumed deadly poison doses at target
473 uint32 spellId
= poison
->GetId();
474 uint32 doses
= poison
->GetStackAmount();
477 for (int i
=0; i
< doses
; i
++)
478 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
480 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster
->GetDummyAura(37169))
484 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
488 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
490 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
492 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
493 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster
->GetDummyAura(37169))
501 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
503 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
506 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
508 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
511 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
513 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
517 case SPELLFAMILY_HUNTER
:
520 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
522 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
525 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
527 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
530 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
532 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
535 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
537 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
538 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
540 // Explosive Trap Effect
541 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
543 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
547 case SPELLFAMILY_PALADIN
:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
552 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
553 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
554 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
555 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
558 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
559 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
560 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
562 stacks
= (*itr
)->GetStackAmount();
565 // + 10% for each application of Holy Vengeance on the target
567 damage
+= damage
* stacks
* 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
572 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
573 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
574 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
575 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
580 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
581 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
582 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
583 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
588 // Add main hand dps * effect[2] amount
589 float averange
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
590 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
591 damage
+= count
* int32(averange
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
593 // Shield of Righteousness
594 else if(m_spellInfo
->SpellFamilyFlags
&0x0010000000000000LL
)
596 damage
+=int32(m_caster
->GetShieldBlockValue());
607 void Spell::EffectDummy(uint32 i
)
609 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
612 // selection by spell family
613 switch(m_spellInfo
->SpellFamilyName
)
615 case SPELLFAMILY_GENERIC
:
617 switch(m_spellInfo
->Id
)
619 case 8063: // Deviate Fish
621 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
627 case 1: spell_id
= 8064; break; // Sleepy
628 case 2: spell_id
= 8065; break; // Invigorate
629 case 3: spell_id
= 8066; break; // Shrink
630 case 4: spell_id
= 8067; break; // Party Time!
631 case 5: spell_id
= 8068; break; // Healthy Spirit
633 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
636 case 8213: // Savory Deviate Delight
638 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
645 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
647 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
649 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
657 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
671 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
673 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
675 switch (m_spellInfo
->Id
)
677 case 12850: damage
*= 0.2f
; break;
678 case 12162: damage
*= 0.4f
; break;
679 case 12868: damage
*= 0.6f
; break;
681 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
685 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
686 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
689 case 13120: // net-o-matic
696 uint32 roll
= urand(0, 99);
698 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
700 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
705 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell
|| !unitTarget
)
714 switch(m_triggeredByAuraSpell
->Id
)
716 case 26467: // Persistent Shield
717 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
720 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
731 Creature
* creatureTarget
= (Creature
*)unitTarget
;
732 creatureTarget
->setDeathState(JUST_DIED
);
733 creatureTarget
->RemoveCorpse();
734 creatureTarget
->SetHealth(0); // just for nice GM-mode view
737 case 16589: // Noggenfogger Elixir
739 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
745 case 1: spell_id
= 16595; break;
746 case 2: spell_id
= 16593; break;
747 default:spell_id
= 16591; break;
750 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
753 case 17251: // Spirit Healer Res
755 if(!unitTarget
|| !m_originalCaster
)
758 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
760 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
761 data
<< unitTarget
->GetGUID();
762 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
766 case 17271: // Test Fetid Skull
768 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
771 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
773 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
776 case 20577: // Cannibalize
778 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
785 Creature
* creatureTarget
= (Creature
*)unitTarget
;
786 if(creatureTarget
->isPet())
789 GameObject
* pGameObj
= new GameObject
;
791 Map
*map
= creatureTarget
->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
795 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
796 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1) )
802 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
803 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
804 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
805 pGameObj
->SetSpellId(m_spellInfo
->Id
);
807 creatureTarget
->setDeathState(JUST_DIED
);
808 creatureTarget
->RemoveCorpse();
809 creatureTarget
->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
814 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
815 data
<< uint64(pGameObj
->GetGUID());
816 m_caster
->SendMessageToSet(&data
,true);
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem
) return;
822 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem
) return;
826 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem
) return;
830 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem
) return;
834 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r
= irand(0, 119);
839 if ( r
< 20 ) // 1/6 polymorph
840 m_caster
->CastSpell(m_caster
,23444,true);
841 else if ( r
< 100 ) // 4/6 evil twin
842 m_caster
->CastSpell(m_caster
,23445,true);
843 else // 1/6 miss the target
844 m_caster
->CastSpell(m_caster
,36902,true);
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster
->CastSpell(m_caster
,23441,true);
851 m_caster
->CastSpell(m_caster
,23446,true);
853 case 23645: // Hourglass Sand
854 m_caster
->RemoveAurasDueToSpell(23170);
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster
->CastSpell(m_caster
,23782,true);
858 m_caster
->CastSpell(m_caster
,23783,true);
860 case 25860: // Reindeer Transformation
862 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
865 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
866 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
868 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed
>= 4.1f
)
872 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
873 else if (flyspeed
>= 3.8f
)
874 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
875 else if (flyspeed
>= 1.6f
)
876 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
877 else if (speed
>= 2.0f
)
878 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
880 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
889 m_caster
->CastSpell(unitTarget
,29294,true);
892 case 28730: // Arcane Torrent (Mana)
894 Aura
* dummy
= m_caster
->GetDummyAura(28734);
897 int32 bp
= damage
* dummy
->GetStackAmount();
898 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
899 m_caster
->RemoveAurasDueToSpell(28734);
903 case 29200: // Purify Helboar Meat
905 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
908 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
910 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
913 case 29858: // Soulshatter
914 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
915 m_caster
->CastSpell(unitTarget
,32835,true);
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem
) return;
919 if(roll_chance_i(86)) // success
920 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
921 else // backfire in 14% casts
922 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
924 case 30507: // Poultryizer
925 if (!m_CastItem
) return;
926 if(roll_chance_i(80)) // success
927 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
929 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
931 case 33060: // Make a Wish
933 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
940 case 1: spell_id
= 33053; break;
941 case 2: spell_id
= 33057; break;
942 case 3: spell_id
= 33059; break;
943 case 4: spell_id
= 33062; break;
944 case 5: spell_id
= 33064; break;
947 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
953 switch(m_caster
->GetAreaId())
955 case 3900: spell_id
= 35743; break;
956 case 3742: spell_id
= 35744; break;
960 m_caster
->CastSpell(m_caster
,spell_id
,true);
963 case 37674: // Chaos Blast
968 int32 basepoints0
= 100;
969 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
978 case 1: newitemid
= 32688; break;
979 case 2: newitemid
= 32689; break;
980 case 3: newitemid
= 32690; break;
981 case 4: newitemid
= 32691; break;
982 case 5: newitemid
= 32692; break;
983 case 6: newitemid
= 32693; break;
984 case 7: newitemid
= 32700; break;
985 case 8: newitemid
= 32701; break;
986 case 9: newitemid
= 32702; break;
987 case 10: newitemid
= 32703; break;
988 case 11: newitemid
= 32704; break;
989 case 12: newitemid
= 32705; break;
990 case 13: newitemid
= 32706; break;
991 case 14: newitemid
= 32707; break;
992 case 15: newitemid
= 32708; break;
993 case 16: newitemid
= 32709; break;
994 case 17: newitemid
= 32710; break;
995 case 18: newitemid
= 32711; break;
996 case 19: newitemid
= 32712; break;
997 case 20: newitemid
= 32713; break;
1002 DoCreateItem(i
,newitemid
);
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1021 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1023 creatureTarget
->setDeathState(JUST_DIED
);
1024 creatureTarget
->RemoveCorpse();
1025 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1031 case 34665: //Administer Antidote
1033 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1039 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1043 uint32 health
= tempSummon
->GetHealth();
1045 float x
= tempSummon
->GetPositionX();
1046 float y
= tempSummon
->GetPositionY();
1047 float z
= tempSummon
->GetPositionZ();
1048 float o
= tempSummon
->GetOrientation();
1049 tempSummon
->UnSummon();
1051 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1055 pCreature
->SetHealth(health
);
1056 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992,pCreature
);
1058 if (pCreature
->AI())
1059 pCreature
->AI()->AttackStart(m_caster
);
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster
->CastSpell(m_caster
, 45009, true);
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster
->CastSpell(m_caster
, 45088, true);
1075 case 50243: // Teach Language
1077 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1083 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1085 // 1000001 - gnomish binary
1086 m_caster
->CastSpell(m_caster
, 50242, true);
1090 // 01001000 - goblin binary
1091 m_caster
->CastSpell(m_caster
, 50246, true);
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1101 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1102 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1104 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1113 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1114 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1116 if (m_caster
->HasAura(reqAuraID
,0))
1117 m_caster
->CastSpell(m_caster
,spellID
,true,NULL
);
1121 return; // additional data for dummy[0]
1128 m_caster
->CastSpell(m_caster
,54586,true);
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo
->SpellIconID
)
1139 // Berserking (troll racial traits)
1142 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1143 int32 melee_mod
= 10;
1144 if (healthPerc
<= 40)
1146 if (healthPerc
< 100 && healthPerc
> 40)
1147 melee_mod
= 10+(100-healthPerc
)/3;
1149 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1
= (5-melee_mod
);
1151 int32 hasteModBasePoints2
= 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1155 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1161 case SPELLFAMILY_MAGE
:
1162 switch(m_spellInfo
->Id
)
1164 case 11958: // Cold Snap
1166 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1173 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1176 uint32 classspell
= itr
->first
;
1177 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1179 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1180 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1181 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1183 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1185 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1186 data
<< uint32(classspell
);
1187 data
<< uint64(m_caster
->GetGUID());
1188 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1195 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1205 case SPELLFAMILY_WARRIOR
:
1207 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1209 int32 chargeBasePoints0
= damage
;
1210 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1214 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1219 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1220 // Glyph of Execution bonus
1221 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1222 rage
+=aura
->GetModifier()->m_amount
;
1224 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1225 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1226 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1227 m_caster
->SetPower(POWER_RAGE
,0);
1231 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1235 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1239 switch(m_spellInfo
->Id
)
1246 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1252 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1253 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1259 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1264 case SPELLFAMILY_WARLOCK
:
1266 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1268 // In 303 exist spirit depend
1269 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1270 switch (m_spellInfo
->Id
)
1272 case 1454: damage
+=spirit
; break;
1273 case 1455: damage
+=spirit
*15/10; break;
1274 case 1456: damage
+=spirit
*2; break;
1275 case 11687: damage
+=spirit
*25/10; break;
1279 case 57946: damage
+=spirit
*3; break;
1281 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1284 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1285 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1286 if(int32(unitTarget
->GetHealth()) > damage
)
1288 // Shouldn't Appear in Combat Log
1289 unitTarget
->ModifyHealth(-damage
);
1291 int32 mana
= damage
;
1292 // Improved Life Tap mod
1293 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1294 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1296 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1297 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1299 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1302 int32 manaFeedVal
= 0;
1303 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1304 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1306 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1307 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1311 manaFeedVal
= manaFeedVal
* mana
/ 100;
1312 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1316 SendCastResult(SPELL_FAILED_FIZZLE
);
1320 case SPELLFAMILY_PRIEST
:
1322 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1329 switch(m_spellInfo
->Id
)
1331 case 47540: hurt
= 47758; heal
= 47757; break;
1332 case 53005: hurt
= 53001; heal
= 52986; break;
1333 case 53006: hurt
= 53002; heal
= 52987; break;
1334 case 53007: hurt
= 53003; heal
= 52988; break;
1336 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1339 if (m_caster
->IsFriendlyTo(unitTarget
))
1340 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1342 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1346 case SPELLFAMILY_DRUID
:
1348 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000100LL
)
1350 //Shapeshifting into an animal form or mounting cancels the effect.
1351 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1353 if(m_triggeredByAuraSpell
)
1354 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1358 //Any effect which causes you to lose control of your character will supress the starfall effect.
1359 if(m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1362 switch(m_spellInfo
->Id
)
1364 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1365 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1366 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1367 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1369 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1374 case SPELLFAMILY_ROGUE
:
1375 switch(m_spellInfo
->Id
)
1379 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1382 Player
*pCaster
= ((Player
*)m_caster
);
1384 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1388 // all poison enchantments is temporary
1389 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1393 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1397 for (int s
=0;s
<3;s
++)
1399 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1402 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1403 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1406 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1409 m_caster
->CastSpell(unitTarget
, 5940, true);
1412 case 14185: // Preparation Rogue
1414 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1417 //immediately finishes the cooldown on certain Rogue abilities
1418 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1419 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1421 uint32 classspell
= itr
->first
;
1422 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1424 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1426 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1428 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1429 data
<< uint32(classspell
);
1430 data
<< uint64(m_caster
->GetGUID());
1431 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1436 case 31231: // Cheat Death
1438 m_caster
->CastSpell(m_caster
,45182,true);
1443 case SPELLFAMILY_HUNTER
:
1445 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1447 if( !unitTarget
|| !unitTarget
->isAlive())
1452 // check dazed affect
1453 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1454 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1456 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1468 switch(m_spellInfo
->Id
)
1470 case 23989: //Readiness talent
1472 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1475 //immediately finishes the cooldown for hunter abilities
1476 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1477 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1479 uint32 classspell
= itr
->first
;
1480 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1482 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1484 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1486 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1487 data
<< uint32(classspell
);
1488 data
<< uint64(m_caster
->GetGUID());
1489 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1494 case 37506: // Scatter Shot
1496 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1499 // break Auto Shot and autohit
1500 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1501 m_caster
->AttackStop();
1502 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1507 case SPELLFAMILY_PALADIN
:
1508 switch(m_spellInfo
->SpellIconID
)
1510 case 156: // Holy Shock
1518 switch(m_spellInfo
->Id
)
1520 case 20473: hurt
= 25912; heal
= 25914; break;
1521 case 20929: hurt
= 25911; heal
= 25913; break;
1522 case 20930: hurt
= 25902; heal
= 25903; break;
1523 case 27174: hurt
= 27176; heal
= 27175; break;
1524 case 33072: hurt
= 33073; heal
= 33074; break;
1525 case 48824: hurt
= 48822; heal
= 48820; break;
1526 case 48825: hurt
= 48823; heal
= 48821; break;
1528 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1532 if(m_caster
->IsFriendlyTo(unitTarget
))
1533 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1535 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1539 case 561: // Judgement of command
1544 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1545 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1549 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1551 // decreased damage (/2) for non-stunned target.
1552 SpellModifier
*mod
= new SpellModifier
;
1553 mod
->op
= SPELLMOD_DAMAGE
;
1555 mod
->type
= SPELLMOD_PCT
;
1556 mod
->spellId
= m_spellInfo
->Id
;
1557 mod
->mask
= 0x0000020000000000LL
;
1560 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1561 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1563 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1566 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1572 switch(m_spellInfo
->Id
)
1574 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1579 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1582 case 31789: // Righteous Defense (step 1)
1584 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1586 // non-standard cast requirement check
1587 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1589 // clear cooldown at fail
1590 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1592 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1594 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1595 data
<< uint32(m_spellInfo
->Id
);
1596 data
<< uint64(m_caster
->GetGUID());
1597 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1600 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1604 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1605 // Clear targets for eff 1
1606 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1607 ihit
->effectMask
&= ~(1<<1);
1609 // not empty (checked)
1610 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1612 // chance to be selected from list
1613 float chance
= 100.0f
/attackers
.size();
1615 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1617 if(!roll_chance_f(chance
))
1620 AddUnitTarget((*aItr
), 1);
1623 // now let next effect cast spell at each target.
1626 case 37877: // Blessing of Faith
1631 uint32 spell_id
= 0;
1632 switch(unitTarget
->getClass())
1634 case CLASS_DRUID
: spell_id
= 37878; break;
1635 case CLASS_PALADIN
: spell_id
= 37879; break;
1636 case CLASS_PRIEST
: spell_id
= 37880; break;
1637 case CLASS_SHAMAN
: spell_id
= 37881; break;
1638 default: return; // ignore for not healing classes
1641 m_caster
->CastSpell(m_caster
,spell_id
,true);
1646 case SPELLFAMILY_SHAMAN
:
1647 //Shaman Rockbiter Weapon
1648 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1650 // TODO: use expect spell for enchant (if exist talent)
1651 // In 3.0.3 no mods present for rockbiter
1652 uint32 spell_id
= 0;
1653 switch(m_spellInfo
->Id
)
1655 case 8017: spell_id
= 36494; break; // Rank 1
1656 case 8018: spell_id
= 36750; break; // Rank 2
1657 case 8019: spell_id
= 36755; break; // Rank 3
1658 case 10399: spell_id
= 36759; break; // Rank 4
1660 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1664 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1668 sLog
.outError("WORLD: unknown spell id %i", spell_id
);
1672 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1675 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1677 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1679 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1681 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1683 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1684 // at calculation applied affect from Elemental Weapons talent
1685 // real enchantment damage-1
1686 spell
->m_currentBasePoints
[1] = damage
-1;
1688 SpellCastTargets targets
;
1689 targets
.setItemTarget( item
);
1690 spell
->prepare(&targets
);
1696 // Healing Stream Totem
1697 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1699 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1702 // Mana Spring Totem
1703 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1705 if(unitTarget
->getPowerType()!=POWER_MANA
)
1707 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1710 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1712 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1714 // Glyph of Mana Tide
1715 Unit
*owner
= m_caster
->GetOwner();
1717 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1718 damage
+=dummy
->GetModifier()->m_amount
;
1719 // Regenerate 6% of Total Mana Every 3 secs
1720 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1721 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1725 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1727 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1729 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1732 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1733 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1734 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1736 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1737 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1738 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1740 m_damage
+= m_damage
* damage
/ 100;
1748 case SPELLFAMILY_DEATHKNIGHT
:
1750 if(m_spellInfo
->SpellFamilyFlags
& 0x002000LL
)
1752 if(m_caster
->IsFriendlyTo(unitTarget
))
1754 if(unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1757 int32 bp
= damage
* 1.5f
;
1758 m_caster
->CastCustomSpell(unitTarget
,47633,&bp
,NULL
,NULL
,true);
1763 m_caster
->CastCustomSpell(unitTarget
,47632,&bp
,NULL
,NULL
,true);
1771 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1773 m_caster
->AddPetAura(petSpell
);
1777 // Script based implementation. Must be used only for not good for implementation in core spell effects
1778 // So called only for not proccessed cases
1780 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
1781 else if(unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
1782 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
1784 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
1787 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1789 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1792 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1796 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1801 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1804 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1806 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1807 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1811 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1816 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1818 SpellCastTargets targets
;
1819 targets
.setUnitTarget( unitTarget
);
1820 spell
->prepare(&targets
);
1822 m_caster
->SetCurrentCastedSpell(spell
);
1823 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1827 void Spell::EffectForceCast(uint32 i
)
1832 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1835 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1839 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1843 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1846 void Spell::EffectTriggerSpell(uint32 i
)
1848 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1851 switch(triggered_spell_id
)
1856 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1857 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1858 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1860 // if this spell is given to NPC it must handle rest by it's own AI
1861 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1864 // get highest rank of the Stealth spell
1866 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1867 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1869 // only highest rank is shown in spell book, so simply check if shown in spell book
1870 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1873 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1877 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1879 spellId
= spellInfo
->Id
;
1884 // no Stealth spell found
1888 // reset cooldown on it if needed
1889 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1890 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1892 m_caster
->CastSpell(m_caster
, spellId
, true);
1896 case 23770: // Sayge's Dark Fortune of *
1897 // not exist, common cooldown can be implemented in scripts if need.
1899 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1902 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1906 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1907 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1910 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1913 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1917 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1918 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1921 // Righteous Defense
1924 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1930 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1931 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1933 // remove all harmful spells on you...
1934 if( // ignore positive and passive auras
1935 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1936 // ignore physical auras
1937 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1939 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1940 iter
= Auras
.begin();
1945 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1948 if (Unit
*pet
= m_caster
->GetPet())
1949 pet
->CastSpell(pet
, 28305, true);
1955 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1959 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1963 // some triggered spells require specific equipment
1964 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1966 // main hand weapon required
1967 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1969 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1971 // skip spell if no weapon in slot or broken
1972 if(!item
|| item
->IsBroken() )
1975 // skip spell if weapon not fit to triggered spell
1976 if(!item
->IsFitToSpellRequirements(spellInfo
))
1980 // offhand hand weapon required
1981 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1983 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1985 // skip spell if no weapon in slot or broken
1986 if(!item
|| item
->IsBroken() )
1989 // skip spell if weapon not fit to triggered spell
1990 if(!item
->IsFitToSpellRequirements(spellInfo
))
1995 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1996 bool instant
= false;
1997 for(uint32 j
= i
+1; j
< 3; ++j
)
1999 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
2009 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
2012 m_TriggerSpells
.push_back(spellInfo
);
2015 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2017 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2020 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2024 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2025 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2030 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2032 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2035 void Spell::EffectJump(uint32 i
)
2037 if(m_caster
->isInFlight())
2040 // Init dest coordinates
2042 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2044 x
= m_targets
.m_destX
;
2045 y
= m_targets
.m_destY
;
2046 z
= m_targets
.m_destZ
;
2048 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2050 // explicit cast data from client or server-side cast
2051 // some spell at client send caster
2052 Unit
* pTarget
= NULL
;
2053 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2054 pTarget
= m_targets
.getUnitTarget();
2055 else if(unitTarget
->getVictim())
2056 pTarget
= m_caster
->getVictim();
2057 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2058 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2060 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2063 o
= m_caster
->GetOrientation();
2067 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2068 o
= m_caster
->GetOrientation();
2070 else if(gameObjTarget
)
2072 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2073 o
= m_caster
->GetOrientation();
2077 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2081 m_caster
->NearTeleportTo(x
,y
,z
,o
,true);
2084 void Spell::EffectTeleportUnits(uint32 i
)
2086 if(!unitTarget
|| unitTarget
->isInFlight())
2089 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2091 case TARGET_INNKEEPER_COORDINATES
:
2093 // Only players can teleport to innkeeper
2094 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2097 ((Player
*)unitTarget
)->TeleportTo(((Player
*)unitTarget
)->m_homebindMapId
,((Player
*)unitTarget
)->m_homebindX
,((Player
*)unitTarget
)->m_homebindY
,((Player
*)unitTarget
)->m_homebindZ
,unitTarget
->GetOrientation(),unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2100 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2102 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2105 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2109 if(st
->target_mapId
==unitTarget
->GetMapId())
2110 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2111 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2112 ((Player
*)unitTarget
)->TeleportTo(st
->target_mapId
,st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2115 case TARGET_BEHIND_VICTIM
:
2117 Unit
*pTarget
= NULL
;
2119 // explicit cast data from client or server-side cast
2120 // some spell at client send caster
2121 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2122 pTarget
= m_targets
.getUnitTarget();
2123 else if(unitTarget
->getVictim())
2124 pTarget
= unitTarget
->getVictim();
2125 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2126 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2128 // Init dest coordinates
2129 float x
= m_targets
.m_destX
;
2130 float y
= m_targets
.m_destY
;
2131 float z
= m_targets
.m_destZ
;
2132 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2133 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2138 // If not exist data for dest location - return
2139 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2141 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2144 // Init dest coordinates
2145 uint32 mapid
= m_caster
->GetMapId();
2146 float x
= m_targets
.m_destX
;
2147 float y
= m_targets
.m_destY
;
2148 float z
= m_targets
.m_destZ
;
2149 float orientation
= unitTarget
->GetOrientation();
2151 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2156 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2157 switch ( m_spellInfo
->Id
)
2159 // Dimensional Ripper - Everlook
2162 int32 r
= irand(0, 119);
2163 if ( r
>= 70 ) // 7/12 success
2165 if ( r
< 100 ) // 4/12 evil twin
2166 m_caster
->CastSpell(m_caster
,23445,true);
2168 m_caster
->CastSpell(m_caster
,23449,true);
2172 // Ultrasafe Transporter: Toshley's Station
2175 if ( roll_chance_i(50) ) // 50% success
2177 int32 rand_eff
= urand(1,7);
2181 // soul split - evil
2182 m_caster
->CastSpell(m_caster
,36900,true);
2185 // soul split - good
2186 m_caster
->CastSpell(m_caster
,36901,true);
2189 // Increase the size
2190 m_caster
->CastSpell(m_caster
,36895,true);
2193 // Decrease the size
2194 m_caster
->CastSpell(m_caster
,36893,true);
2199 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2200 m_caster
->CastSpell(m_caster
,36897,true);
2202 m_caster
->CastSpell(m_caster
,36899,true);
2207 m_caster
->CastSpell(m_caster
,36940,true);
2211 m_caster
->CastSpell(m_caster
,23445,true);
2217 // Dimensional Ripper - Area 52
2220 if ( roll_chance_i(50) ) // 50% success
2222 int32 rand_eff
= urand(1,4);
2226 // soul split - evil
2227 m_caster
->CastSpell(m_caster
,36900,true);
2230 // soul split - good
2231 m_caster
->CastSpell(m_caster
,36901,true);
2234 // Increase the size
2235 m_caster
->CastSpell(m_caster
,36895,true);
2240 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2241 m_caster
->CastSpell(m_caster
,36897,true);
2243 m_caster
->CastSpell(m_caster
,36899,true);
2253 void Spell::EffectApplyAura(uint32 i
)
2258 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2259 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2260 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2263 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2267 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2269 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2271 // Now Reduce spell duration using data received at spell hit
2272 int32 duration
= Aur
->GetAuraMaxDuration();
2273 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2274 Aur
->setDiminishGroup(m_diminishGroup
);
2276 // if Aura removed and deleted, do not continue.
2277 if(duration
== 0 && !(Aur
->IsPermanent()))
2283 if(duration
!= Aur
->GetAuraMaxDuration())
2285 Aur
->SetAuraMaxDuration(duration
);
2286 Aur
->SetAuraDuration(duration
);
2289 bool added
= unitTarget
->AddAura(Aur
);
2291 // Aura not added and deleted in AddAura call;
2295 // found crash at character loading, broken pointer to Aur...
2296 // Aur was deleted in AddAura()...
2300 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2301 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2302 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2305 void Spell::EffectUnlearnSpecialization( uint32 i
)
2307 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2310 Player
*_player
= (Player
*)unitTarget
;
2311 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2313 _player
->removeSpell(spellToUnlearn
);
2315 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2318 void Spell::EffectPowerDrain(uint32 i
)
2320 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2323 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2327 if(!unitTarget
->isAlive())
2329 if(unitTarget
->getPowerType() != drain_power
)
2334 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2336 //add spell damage bonus
2337 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2339 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2340 uint32 power
= damage
;
2341 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2342 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2345 if(curPower
< power
)
2346 new_damage
= curPower
;
2350 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2352 // Don`t restore from self drain
2353 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2355 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2356 if(manaMultiplier
==0)
2359 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2360 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2362 int32 gain
= int32(new_damage
*manaMultiplier
);
2364 m_caster
->ModifyPower(POWER_MANA
,gain
);
2366 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2370 void Spell::EffectSendEvent(uint32 EffectIndex
)
2373 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2375 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2376 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2379 void Spell::EffectPowerBurn(uint32 i
)
2381 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2384 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2388 if(!unitTarget
->isAlive())
2390 if(unitTarget
->getPowerType()!=powertype
)
2395 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2396 if(m_spellInfo
->ManaCostPercentage
)
2398 uint32 maxdamage
= m_caster
->GetMaxPower(powertype
) * damage
* 2 / 100;
2399 damage
= unitTarget
->GetMaxPower(powertype
) * damage
/ 100;
2400 if(damage
> maxdamage
) damage
= maxdamage
;
2403 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2405 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2406 uint32 power
= damage
;
2407 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2408 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2410 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2412 unitTarget
->ModifyPower(powertype
,-new_damage
);
2413 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2415 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2416 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2418 new_damage
= int32(new_damage
*multiplier
);
2419 m_damage
+=new_damage
;
2422 void Spell::EffectHeal( uint32
/*i*/ )
2424 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2426 // Try to get original caster
2427 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2429 // Skip if m_originalCaster not available
2433 int32 addhealth
= damage
;
2435 // Vessel of the Naaru (Vial of the Sunwell trinket)
2436 if (m_spellInfo
->Id
== 45064)
2438 // Amount of heal - depends from stacked Holy Energy
2439 int damageAmount
= 0;
2440 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2441 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2442 if((*i
)->GetId() == 45062)
2443 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2445 m_caster
->RemoveAurasDueToSpell(45062);
2447 addhealth
+= damageAmount
;
2449 // Swiftmend - consumes Regrowth or Rejuvenation
2450 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2452 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2453 // find most short by duration
2454 Aura
*targetAura
= NULL
;
2455 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2457 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2458 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2460 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2467 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2473 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2478 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2479 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2480 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2482 addhealth
+= tickheal
* tickcount
;
2485 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2487 m_healing
+=addhealth
;
2491 void Spell::EffectHealPct( uint32
/*i*/ )
2493 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2495 // Try to get original caster
2496 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2498 // Skip if m_originalCaster not available
2502 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2503 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2504 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DAMAGE
, addhealth
, this);
2506 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2508 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2509 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2511 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2512 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2513 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2517 void Spell::EffectHealMechanical( uint32
/*i*/ )
2519 // Mechanic creature type should be correctly checked by targetCreatureType field
2520 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2522 // Try to get original caster
2523 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2525 // Skip if m_originalCaster not available
2529 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2530 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2531 unitTarget
->ModifyHealth( int32(damage
) );
2535 void Spell::EffectHealthLeech(uint32 i
)
2539 if(!unitTarget
->isAlive())
2545 sLog
.outDebug("HealthLeech :%i", damage
);
2547 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2549 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2550 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2552 int32 new_damage
= int32(damage
*multiplier
);
2553 uint32 curHealth
= unitTarget
->GetHealth();
2554 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2555 if(curHealth
< new_damage
)
2556 new_damage
= curHealth
;
2558 if(m_caster
->isAlive())
2560 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2562 m_caster
->ModifyHealth(new_damage
);
2564 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2565 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2567 // m_healthLeech+=tmpvalue;
2568 // m_damage+=new_damage;
2571 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2573 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2576 Player
* player
= (Player
*)unitTarget
;
2578 uint32 newitemid
= itemtype
;
2579 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2582 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2588 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2589 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2591 int32 basePoints
= m_currentBasePoints
[i
];
2592 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2594 num_to_add
= basePoints
+ irand(1, randomPoints
);
2596 num_to_add
= basePoints
+ 1;
2598 else if (pProto
->MaxCount
== 1)
2600 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2602 int32 basePoints
= m_currentBasePoints
[i
];
2603 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2604 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2611 if (num_to_add
> pProto
->GetMaxStackSize())
2612 num_to_add
= pProto
->GetMaxStackSize();
2614 // init items_count to 1, since 1 item will be created regardless of specialization
2616 // the chance to create additional items
2617 float additionalCreateChance
=0.0f
;
2618 // the maximum number of created additional items
2619 uint8 additionalMaxNum
=0;
2620 // get the chance and maximum number for creating extra items
2621 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2623 // roll with this chance till we roll not to create or we create the max num
2624 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2628 // really will be created more items
2629 num_to_add
*= items_count
;
2631 // can the player store the new item?
2632 ItemPosCountVec dest
;
2633 uint32 no_space
= 0;
2634 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2635 if( msg
!= EQUIP_ERR_OK
)
2637 // convert to possible store amount
2638 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2639 num_to_add
-= no_space
;
2642 // if not created by another reason from full inventory or unique items amount limitation
2643 player
->SendEquipError( msg
, NULL
, NULL
);
2650 // create the new item and store it
2651 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2653 // was it successful? return error if not
2656 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2660 // set the "Crafted by ..." property of the item
2661 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2662 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2664 // send info to the client
2666 player
->SendNewItem(pItem
, num_to_add
, true, true);
2668 // we succeeded in creating at least one item, so a levelup is possible
2669 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2672 // for battleground marks send by mail if not add all expected
2675 BattleGroundTypeId bgType
;
2676 switch(m_spellInfo
->Id
)
2678 case SPELL_AV_MARK_WINNER
:
2679 case SPELL_AV_MARK_LOSER
:
2680 bgType
= BATTLEGROUND_AV
;
2682 case SPELL_WS_MARK_WINNER
:
2683 case SPELL_WS_MARK_LOSER
:
2684 bgType
= BATTLEGROUND_WS
;
2686 case SPELL_AB_MARK_WINNER
:
2687 case SPELL_AB_MARK_LOSER
:
2688 bgType
= BATTLEGROUND_AB
;
2694 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2695 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2699 void Spell::EffectCreateItem(uint32 i
)
2701 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2704 void Spell::EffectCreateItem2(uint32 i
)
2706 // special case: generate using spell_loot_template
2707 if(!m_spellInfo
->EffectItemType
[i
])
2709 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2712 // create some random items
2713 ((Player
*)m_caster
)->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
2716 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2719 void Spell::EffectPersistentAA(uint32 i
)
2721 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2723 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2724 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2726 int32 duration
= GetSpellDuration(m_spellInfo
);
2727 DynamicObject
* dynObj
= new DynamicObject
;
2728 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
))
2733 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2734 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2735 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2736 m_caster
->AddDynObject(dynObj
);
2737 dynObj
->GetMap()->Add(dynObj
);
2740 void Spell::EffectEnergize(uint32 i
)
2744 if(!unitTarget
->isAlive())
2747 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2750 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2752 // Some level depends spells
2755 switch (m_spellInfo
->Id
)
2759 level_diff
= m_caster
->getLevel() - 40;
2764 level_diff
= m_caster
->getLevel() - 60;
2769 level_diff
= m_caster
->getLevel() - 60;
2777 damage
-= multiplier
* level_diff
;
2782 if(unitTarget
->GetMaxPower(power
) == 0)
2785 unitTarget
->ModifyPower(power
,damage
);
2786 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2788 // Mad Alchemist's Potion
2789 if (m_spellInfo
->Id
== 45051)
2791 // find elixirs on target
2792 uint32 elixir_mask
= 0;
2793 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2794 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2796 uint32 spell_id
= itr
->second
->GetId();
2797 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2798 elixir_mask
|= mask
;
2801 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2802 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2804 // get all available elixirs by mask and spell level
2805 std::vector
<uint32
> elixirs
;
2806 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2807 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2809 if (itr
->second
& elixir_mask
)
2811 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2814 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2815 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2818 elixirs
.push_back(itr
->first
);
2822 if (!elixirs
.empty())
2824 // cast random elixir on target
2825 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2826 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2831 void Spell::EffectEnergisePct(uint32 i
)
2835 if(!unitTarget
->isAlive())
2838 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2841 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2843 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2847 uint32 gain
= damage
* maxPower
/ 100;
2848 unitTarget
->ModifyPower(power
, gain
);
2849 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2852 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2854 Player
* player
= (Player
*)m_caster
;
2860 if (Script
->GOHello(player
, gameObjTarget
))
2863 switch (gameObjTarget
->GetGoType())
2865 case GAMEOBJECT_TYPE_DOOR
:
2866 case GAMEOBJECT_TYPE_BUTTON
:
2867 gameObjTarget
->UseDoorOrButton();
2868 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2871 case GAMEOBJECT_TYPE_QUESTGIVER
:
2872 // start or end quest
2873 player
->PrepareQuestMenu(guid
);
2874 player
->SendPreparedQuest(guid
);
2877 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2878 // triggering linked GO
2879 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2880 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2883 case GAMEOBJECT_TYPE_GOOBER
:
2884 // goober_scripts can be triggered if the player don't have the quest
2885 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2887 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2888 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2891 // cast goober spell
2892 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2893 ///Quest require to be active for GO using
2894 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2897 gameObjTarget
->AddUniqueUse(player
);
2898 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2900 //TODO? Objective counting called without spell check but with quest objective check
2901 // if send spell id then this line will duplicate to spell casting call (double counting)
2902 // So we or have this line and not required in quest_template have reqSpellIdN
2903 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2904 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2906 // triggering linked GO
2907 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2908 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2912 case GAMEOBJECT_TYPE_CHEST
:
2913 // TODO: possible must be moved to loot release (in different from linked triggering)
2914 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2916 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2917 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2920 // triggering linked GO
2921 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2922 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2924 // Don't return, let loots been taken
2929 player
->SendLoot(guid
, loottype
);
2932 void Spell::EffectOpenLock(uint32 effIndex
)
2934 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2936 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2940 Player
* player
= (Player
*)m_caster
;
2948 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2949 // Arathi Basin banner opening !
2950 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2951 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2953 //CanUseBattleGroundObject() already called in CheckCast()
2954 // in battleground check
2955 if(BattleGround
*bg
= player
->GetBattleGround())
2957 // check if it's correct bg
2958 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2959 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2963 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2965 //CanUseBattleGroundObject() already called in CheckCast()
2966 // in battleground check
2967 if(BattleGround
*bg
= player
->GetBattleGround())
2969 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2970 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2974 lockId
= gameObjTarget
->GetLockId();
2975 guid
= gameObjTarget
->GetGUID();
2979 lockId
= itemTarget
->GetProto()->LockID
;
2980 guid
= itemTarget
->GetGUID();
2984 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2988 SkillType skillId
= SKILL_NONE
;
2989 int32 reqSkillValue
= 0;
2992 SpellCastResult res
= CanOpenLock(effIndex
,lockId
,skillId
,reqSkillValue
,skillValue
);
2993 if(res
!= SPELL_CAST_OK
)
2995 SendCastResult(res
);
2999 SendLoot(guid
, LOOT_SKINNING
);
3001 // not allow use skill grow at item base open
3002 if(!m_CastItem
&& skillId
!= SKILL_NONE
)
3004 // update skill if really known
3005 if(uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3009 // Allow one skill-up until respawned
3010 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3011 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
) )
3012 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3017 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3023 void Spell::EffectSummonChangeItem(uint32 i
)
3025 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3028 Player
*player
= (Player
*)m_caster
;
3030 // applied only to using item
3034 // ... only to item in own inventory/bank/equip_slot
3035 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3038 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3042 uint16 pos
= m_CastItem
->GetPos();
3044 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3048 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3050 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3051 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3054 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3056 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3057 player
->DurabilityLoss(pNewItem
, loosePercent
);
3060 if( player
->IsInventoryPos( pos
) )
3062 ItemPosCountVec dest
;
3063 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3064 if( msg
== EQUIP_ERR_OK
)
3066 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3068 // prevent crash at access and unexpected charges counting with item update queue corrupt
3069 if(m_CastItem
==m_targets
.getItemTarget())
3070 m_targets
.setItemTarget(NULL
);
3074 player
->StoreItem( dest
, pNewItem
, true);
3078 else if( player
->IsBankPos ( pos
) )
3080 ItemPosCountVec dest
;
3081 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3082 if( msg
== EQUIP_ERR_OK
)
3084 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3086 // prevent crash at access and unexpected charges counting with item update queue corrupt
3087 if(m_CastItem
==m_targets
.getItemTarget())
3088 m_targets
.setItemTarget(NULL
);
3092 player
->BankItem( dest
, pNewItem
, true);
3096 else if( player
->IsEquipmentPos ( pos
) )
3099 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3100 if( msg
== EQUIP_ERR_OK
)
3102 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3104 // prevent crash at access and unexpected charges counting with item update queue corrupt
3105 if(m_CastItem
==m_targets
.getItemTarget())
3106 m_targets
.setItemTarget(NULL
);
3110 player
->EquipItem( dest
, pNewItem
, true);
3111 player
->AutoUnequipOffhandIfNeed();
3120 void Spell::EffectOpenSecretSafe(uint32 i
)
3122 EffectOpenLock(i
); //no difference for now
3125 void Spell::EffectProficiency(uint32
/*i*/)
3127 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3129 Player
*p_target
= (Player
*)unitTarget
;
3131 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3132 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3134 p_target
->AddWeaponProficiency(subClassMask
);
3135 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3137 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3139 p_target
->AddArmorProficiency(subClassMask
);
3140 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3144 void Spell::EffectApplyAreaAura(uint32 i
)
3148 if(!unitTarget
->isAlive())
3151 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3152 unitTarget
->AddAura(Aur
);
3155 void Spell::EffectSummonType(uint32 i
)
3157 switch(m_spellInfo
->EffectMiscValueB
[i
])
3159 case SUMMON_TYPE_GUARDIAN
:
3160 case SUMMON_TYPE_POSESSED
:
3161 case SUMMON_TYPE_POSESSED2
:
3162 case SUMMON_TYPE_FORCE_OF_NATURE
:
3163 case SUMMON_TYPE_GUARDIAN2
:
3164 EffectSummonGuardian(i
);
3166 case SUMMON_TYPE_WILD
:
3167 EffectSummonWild(i
);
3169 case SUMMON_TYPE_DEMON
:
3170 EffectSummonDemon(i
);
3172 case SUMMON_TYPE_SUMMON
:
3175 case SUMMON_TYPE_CRITTER
:
3176 case SUMMON_TYPE_CRITTER2
:
3177 case SUMMON_TYPE_CRITTER3
:
3178 EffectSummonCritter(i
);
3180 case SUMMON_TYPE_TOTEM_SLOT1
:
3181 case SUMMON_TYPE_TOTEM_SLOT2
:
3182 case SUMMON_TYPE_TOTEM_SLOT3
:
3183 case SUMMON_TYPE_TOTEM_SLOT4
:
3184 case SUMMON_TYPE_TOTEM
:
3185 EffectSummonTotem(i
);
3187 case SUMMON_TYPE_UNKNOWN1
:
3188 case SUMMON_TYPE_UNKNOWN2
:
3189 case SUMMON_TYPE_UNKNOWN3
:
3190 case SUMMON_TYPE_UNKNOWN4
:
3191 case SUMMON_TYPE_UNKNOWN5
:
3194 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3199 void Spell::EffectSummon(uint32 i
)
3201 if(m_caster
->GetPetGUID())
3206 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3209 uint32 level
= m_caster
->getLevel();
3210 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3212 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3214 // set timer for unsummon
3215 int32 duration
= GetSpellDuration(m_spellInfo
);
3217 spawnCreature
->SetDuration(duration
);
3222 Map
*map
= m_caster
->GetMap();
3223 uint32 pet_number
= objmgr
.GeneratePetNumber();
3224 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_caster
->GetPhaseMask(),
3225 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3227 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3228 delete spawnCreature
;
3232 // Summon in dest location
3234 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3236 x
= m_targets
.m_destX
;
3237 y
= m_targets
.m_destY
;
3238 z
= m_targets
.m_destZ
;
3241 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3243 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3245 if(!spawnCreature
->IsPositionValid())
3247 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3248 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3249 delete spawnCreature
;
3253 // set timer for unsummon
3254 int32 duration
= GetSpellDuration(m_spellInfo
);
3256 spawnCreature
->SetDuration(duration
);
3258 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3259 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3260 spawnCreature
->setPowerType(POWER_MANA
);
3261 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3262 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3263 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3264 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3265 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3266 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3267 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3268 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3269 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3271 spawnCreature
->InitStatsForLevel(level
);
3273 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3275 spawnCreature
->AIM_Initialize();
3276 spawnCreature
->InitPetCreateSpells();
3277 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3278 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3280 std::string name
= m_caster
->GetName();
3281 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3282 spawnCreature
->SetName( name
);
3284 map
->Add((Creature
*)spawnCreature
);
3286 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3288 m_caster
->SetPet(spawnCreature
);
3289 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3290 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3291 ((Player
*)m_caster
)->PetSpellInitialize();
3295 void Spell::EffectLearnSpell(uint32 i
)
3300 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3302 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3303 EffectLearnPetSpell(i
);
3308 Player
*player
= (Player
*)unitTarget
;
3310 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3311 player
->learnSpell(spellToLearn
,false);
3313 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3316 void Spell::EffectDispel(uint32 i
)
3321 // Fill possible dispell list
3322 std::vector
<Aura
*> dispel_list
;
3324 // Create dispel mask by dispel type
3325 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3326 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3327 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3328 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3330 Aura
*aur
= (*itr
).second
;
3331 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3333 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3335 bool positive
= true;
3336 if (!aur
->IsPositive())
3339 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3341 // do not remove positive auras if friendly target
3342 // negative auras if non-friendly target
3343 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3346 // Add aura to dispel list
3347 dispel_list
.push_back(aur
);
3350 // Ok if exist some buffs for dispel try dispel it
3351 if (!dispel_list
.empty())
3353 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3354 std::list
< uint32
> fail_list
; // spell_id
3355 int32 list_size
= dispel_list
.size();
3356 // Dispell N = damage buffs (or while exist buffs for dispel)
3357 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3359 // Random select buff for dispel
3360 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3362 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3363 // Base dispel chance
3364 // TODO: possible chance depend from spell level??
3365 int32 miss_chance
= 0;
3366 // Apply dispel mod from aura caster
3367 if (Unit
*caster
= aur
->GetCaster())
3369 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3370 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3373 if (roll_chance_i(miss_chance
))
3374 fail_list
.push_back(aur
->GetId());
3376 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3377 // Remove buff from list for prevent doubles
3378 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3380 Aura
*dispeled
= *j
;
3381 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3383 j
= dispel_list
.erase(j
);
3390 // Send success log and really remove auras
3391 if (!success_list
.empty())
3393 int32 count
= success_list
.size();
3394 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3395 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3396 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3397 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3398 data
<< uint8(0); // not used
3399 data
<< uint32(count
); // count
3400 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3402 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3403 data
<< uint32(spellInfo
->Id
); // Spell Id
3404 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3405 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3407 m_caster
->SendMessageToSet(&data
, true);
3411 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3413 uint32 heal_spell
= 0;
3414 switch (m_spellInfo
->Id
)
3416 case 19505: heal_spell
= 19658; break;
3417 case 19731: heal_spell
= 19732; break;
3418 case 19734: heal_spell
= 19733; break;
3419 case 19736: heal_spell
= 19735; break;
3420 case 27276: heal_spell
= 27278; break;
3421 case 27277: heal_spell
= 27279; break;
3423 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3427 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3430 // Send fail log to client
3431 if (!fail_list
.empty())
3433 // Failed to dispell
3434 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3435 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3436 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3437 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3438 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3439 data
<< uint32(*j
); // Spell Id
3440 m_caster
->SendMessageToSet(&data
, true);
3445 void Spell::EffectDualWield(uint32
/*i*/)
3447 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3448 ((Player
*)unitTarget
)->SetCanDualWield(true);
3451 void Spell::EffectPull(uint32
/*i*/)
3453 // TODO: create a proper pull towards distract spell center for distract
3454 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3457 void Spell::EffectDistract(uint32
/*i*/)
3459 // Check for possible target
3460 if (!unitTarget
|| unitTarget
->isInCombat())
3463 // target must be OK to do this
3464 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3467 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3469 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3471 // For players just turn them
3473 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3474 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3475 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3479 // Set creature Distracted, Stop it, And turn it
3480 unitTarget
->SetOrientation(angle
);
3481 unitTarget
->StopMoving();
3482 unitTarget
->GetMotionMaster()->MoveDistract(damage
*IN_MILISECONDS
);
3486 void Spell::EffectPickPocket(uint32
/*i*/)
3488 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3491 // victim must be creature and attackable
3492 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3495 // victim have to be alive and humanoid or undead
3496 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3498 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3500 if (chance
> irand(0, 19))
3502 // Stealing successful
3503 //sLog.outDebug("Sending loot from pickpocket");
3504 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3508 // Reveal action + get attack
3509 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3510 if (((Creature
*)unitTarget
)->AI())
3511 ((Creature
*)unitTarget
)->AI()->AttackedBy(m_caster
);
3516 void Spell::EffectAddFarsight(uint32 i
)
3518 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3519 int32 duration
= GetSpellDuration(m_spellInfo
);
3520 DynamicObject
* dynObj
= new DynamicObject
;
3521 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
))
3526 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3527 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3528 m_caster
->AddDynObject(dynObj
);
3529 dynObj
->GetMap()->Add(dynObj
);
3530 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3531 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3534 void Spell::EffectSummonWild(uint32 i
)
3536 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3540 uint32 level
= m_caster
->getLevel();
3542 // level of creature summoned using engineering item based at engineering skill level
3543 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3545 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3546 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3548 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3556 // select center of summon position
3557 float center_x
= m_targets
.m_destX
;
3558 float center_y
= m_targets
.m_destY
;
3559 float center_z
= m_targets
.m_destZ
;
3561 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3563 int32 amount
= damage
> 0 ? damage
: 1;
3565 for(int32 count
= 0; count
< amount
; ++count
)
3568 // If dest location if present
3569 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3571 // Summon 1 unit in dest location
3574 px
= m_targets
.m_destX
;
3575 py
= m_targets
.m_destY
;
3576 pz
= m_targets
.m_destZ
;
3578 // Summon in random point all other units if location present
3580 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3582 // Summon if dest location not present near caster
3584 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3586 int32 duration
= GetSpellDuration(m_spellInfo
);
3588 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3590 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3594 void Spell::EffectSummonGuardian(uint32 i
)
3596 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3600 // Jewelery statue case (totem like)
3601 if(m_spellInfo
->SpellIconID
==2056)
3603 EffectSummonTotem(i
);
3607 // set timer for unsummon
3608 int32 duration
= GetSpellDuration(m_spellInfo
);
3610 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3611 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3612 // so this code hack in fact
3613 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3614 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3615 return; // find old guardian, ignore summon
3617 // in another case summon new
3618 uint32 level
= m_caster
->getLevel();
3620 // level of pet summoned using engineering item based at engineering skill level
3621 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3623 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3624 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3626 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3634 // select center of summon position
3635 float center_x
= m_targets
.m_destX
;
3636 float center_y
= m_targets
.m_destY
;
3637 float center_z
= m_targets
.m_destZ
;
3639 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3641 int32 amount
= damage
> 0 ? damage
: 1;
3643 for(int32 count
= 0; count
< amount
; ++count
)
3645 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3647 Map
*map
= m_caster
->GetMap();
3648 uint32 pet_number
= objmgr
.GeneratePetNumber();
3649 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3650 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3652 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3653 delete spawnCreature
;
3658 // If dest location if present
3659 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3661 // Summon 1 unit in dest location
3664 px
= m_targets
.m_destX
;
3665 py
= m_targets
.m_destY
;
3666 pz
= m_targets
.m_destZ
;
3668 // Summon in random point all other units if location present
3670 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3672 // Summon if dest location not present near caster
3674 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3676 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3678 if(!spawnCreature
->IsPositionValid())
3680 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3681 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3682 delete spawnCreature
;
3687 spawnCreature
->SetDuration(duration
);
3689 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3690 spawnCreature
->setPowerType(POWER_MANA
);
3691 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3692 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3693 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3694 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3695 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3696 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3697 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3699 spawnCreature
->InitStatsForLevel(level
);
3700 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3702 spawnCreature
->AIM_Initialize();
3704 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3705 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3707 map
->Add((Creature
*)spawnCreature
);
3711 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3716 if(unitTarget
->isInFlight())
3719 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3722 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3724 unitTarget
->NearTeleportTo(fx
,fy
,fz
,-m_caster
->GetOrientation(),unitTarget
==m_caster
);
3727 void Spell::EffectLearnSkill(uint32 i
)
3729 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3735 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3736 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3737 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3740 void Spell::EffectAddHonor(uint32
/*i*/)
3742 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3745 // not scale value for item based reward (/10 value expected)
3748 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/10);
3749 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());
3753 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3756 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
3757 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
3758 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
3762 //maybe we have correct honor_gain in damage already
3763 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3764 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3768 void Spell::EffectTradeSkill(uint32
/*i*/)
3770 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3772 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3773 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3774 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3777 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3779 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3784 Player
* p_caster
= (Player
*)m_caster
;
3786 // not grow at item use at item case
3787 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3789 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3793 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3797 // item can be in trade slot and have owner diff. from caster
3798 Player
* item_owner
= itemTarget
->GetOwner();
3802 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3804 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3805 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3806 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3807 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3810 // remove old enchanting before applying new if equipped
3811 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3813 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3815 // add new enchanting if equipped
3816 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3819 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3821 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3826 Player
* p_caster
= (Player
*)m_caster
;
3828 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3832 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3836 // support only enchantings with add socket in this slot
3838 bool add_socket
= false;
3839 for(int i
= 0; i
< 3; ++i
)
3841 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3849 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.",
3850 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3855 // item can be in trade slot and have owner diff. from caster
3856 Player
* item_owner
= itemTarget
->GetOwner();
3860 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3862 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3863 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3864 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3865 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3868 // remove old enchanting before applying new if equipped
3869 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3871 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3873 // add new enchanting if equipped
3874 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3877 void Spell::EffectEnchantItemTmp(uint32 i
)
3879 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3882 Player
* p_caster
= (Player
*)m_caster
;
3887 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3889 // Shaman Rockbiter Weapon
3890 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3892 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3894 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3895 // with already applied percent bonus from Elemental Weapons talent
3896 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3897 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3898 switch(enchnting_damage
)
3901 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3903 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3904 case 5: enchant_id
= 3025; break; // 20%
3906 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3907 case 7: enchant_id
= 3027; break; // 20%
3909 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3910 case 10: enchant_id
= 503; break; // 14%
3911 case 11: enchant_id
= 3031; break; // 20%
3913 case 15: enchant_id
= 3035; break; // 0%
3914 case 16: enchant_id
= 1663; break; // 7%
3915 case 17: enchant_id
= 3033; break; // 14%
3916 case 18: enchant_id
= 3034; break; // 20%
3918 case 28: enchant_id
= 3038; break; // 0%
3919 case 29: enchant_id
= 683; break; // 7%
3920 case 31: enchant_id
= 3036; break; // 14%
3921 case 33: enchant_id
= 3037; break; // 20%
3923 case 40: enchant_id
= 3041; break; // 0%
3924 case 42: enchant_id
= 1664; break; // 7%
3925 case 45: enchant_id
= 3039; break; // 14%
3926 case 48: enchant_id
= 3040; break; // 20%
3928 case 49: enchant_id
= 3044; break; // 0%
3929 case 52: enchant_id
= 2632; break; // 7%
3930 case 55: enchant_id
= 3042; break; // 14%
3931 case 58: enchant_id
= 3043; break; // 20%
3933 case 62: enchant_id
= 2633; break; // 0%
3934 case 66: enchant_id
= 3018; break; // 7%
3935 case 70: enchant_id
= 3019; break; // 14%
3936 case 74: enchant_id
= 3020; break; // 20%
3938 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3945 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3949 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3952 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3956 // select enchantment duration
3959 // rogue family enchantments exception by duration
3960 if(m_spellInfo
->Id
==38615)
3961 duration
= 1800; // 30 mins
3962 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3963 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3964 duration
= 3600; // 1 hour
3965 // shaman family enchantments
3966 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3967 duration
= 1800; // 30 mins
3968 // other cases with this SpellVisual already selected
3969 else if(m_spellInfo
->SpellVisual
[0]==215)
3970 duration
= 1800; // 30 mins
3971 // some fishing pole bonuses
3972 else if(m_spellInfo
->SpellVisual
[0]==563)
3973 duration
= 600; // 10 mins
3974 // shaman rockbiter enchantments
3975 else if(m_spellInfo
->SpellVisual
[0]==0)
3976 duration
= 1800; // 30 mins
3977 else if(m_spellInfo
->Id
==29702)
3978 duration
= 300; // 5 mins
3979 else if(m_spellInfo
->Id
==37360)
3980 duration
= 300; // 5 mins
3983 duration
= 3600; // 1 hour
3985 // item can be in trade slot and have owner diff. from caster
3986 Player
* item_owner
= itemTarget
->GetOwner();
3990 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3992 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3993 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3994 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3995 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3998 // remove old enchanting before applying new if equipped
3999 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
4001 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
4003 // add new enchanting if equipped
4004 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
4007 void Spell::EffectTameCreature(uint32
/*i*/)
4009 if(m_caster
->GetPetGUID())
4015 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4018 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4020 if(creatureTarget
->isPet())
4023 if(m_caster
->getClass() != CLASS_HUNTER
)
4026 // cast finish successfully
4027 //SendChannelUpdate(0);
4030 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4032 // kill original creature
4033 creatureTarget
->setDeathState(JUST_DIED
);
4034 creatureTarget
->RemoveCorpse();
4035 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4037 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4039 // prepare visual effect for levelup
4040 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4043 pet
->GetMap()->Add((Creature
*)pet
);
4045 // visual effect for levelup
4046 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4048 // caster have pet now
4049 m_caster
->SetPet(pet
);
4051 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4053 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4054 ((Player
*)m_caster
)->PetSpellInitialize();
4058 void Spell::EffectSummonPet(uint32 i
)
4060 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4062 Pet
*OldSummon
= m_caster
->GetPet();
4064 // if pet requested type already exist
4067 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4069 // pet in corpse state can't be summoned
4070 if( OldSummon
->isDead() )
4073 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4074 OldSummon
->SetMapId(m_caster
->GetMapId());
4077 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4079 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4080 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4082 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4084 ((Player
*)m_caster
)->PetSpellInitialize();
4089 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4090 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4095 Pet
* NewSummon
= new Pet
;
4097 // petentry==0 for hunter "call pet" (current pet summoned if any)
4098 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4100 if(NewSummon
->getPetType()==SUMMON_PET
)
4102 // Remove Demonic Sacrifice auras (known pet)
4103 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4104 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4106 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4108 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4109 itr
= auraClassScripts
.begin();
4119 // not error in case fail hunter call pet
4126 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4130 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4135 Map
*map
= m_caster
->GetMap();
4136 uint32 pet_number
= objmgr
.GeneratePetNumber();
4137 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4138 petentry
, pet_number
))
4145 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4147 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4149 if(!NewSummon
->IsPositionValid())
4151 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4152 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4157 uint32 petlevel
= m_caster
->getLevel();
4158 NewSummon
->setPetType(SUMMON_PET
);
4160 uint32 faction
= m_caster
->getFaction();
4161 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4163 if ( ((Creature
*)m_caster
)->isTotem() )
4164 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4166 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4169 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4170 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4171 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4172 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4173 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4174 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4175 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4176 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4177 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4178 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4180 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4181 // this enables pet details window (Shift+P)
4183 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4184 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4185 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4187 NewSummon
->InitStatsForLevel(petlevel
);
4188 NewSummon
->InitPetCreateSpells();
4189 NewSummon
->InitTalentForLevel();
4191 if(NewSummon
->getPetType()==SUMMON_PET
)
4193 // Remove Demonic Sacrifice auras (new pet)
4194 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4195 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4197 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4199 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4200 itr
= auraClassScripts
.begin();
4206 // generate new name for summon pet
4207 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4208 if(!new_name
.empty())
4209 NewSummon
->SetName(new_name
);
4211 else if(NewSummon
->getPetType()==HUNTER_PET
)
4212 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4214 NewSummon
->AIM_Initialize();
4215 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4216 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4218 map
->Add((Creature
*)NewSummon
);
4220 m_caster
->SetPet(NewSummon
);
4221 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4223 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4225 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4226 ((Player
*)m_caster
)->PetSpellInitialize();
4230 void Spell::EffectLearnPetSpell(uint32 i
)
4232 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4235 Player
*_player
= (Player
*)m_caster
;
4237 Pet
*pet
= _player
->GetPet();
4243 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4244 if(!learn_spellproto
)
4247 pet
->learnSpell(learn_spellproto
->Id
);
4249 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4250 _player
->PetSpellInitialize();
4253 void Spell::EffectTaunt(uint32
/*i*/)
4255 // this effect use before aura Taunt apply for prevent taunt already attacking target
4256 // for spell as marked "non effective at already attacking target"
4257 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4259 if(unitTarget
->getVictim()==m_caster
)
4261 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4266 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4267 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4268 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4271 void Spell::EffectWeaponDmg(uint32 i
)
4275 if(!unitTarget
->isAlive())
4278 // multiple weapon dmg effect workaround
4279 // execute only the last weapon damage
4280 // and handle all effects at once
4281 for (int j
= 0; j
< 3; j
++)
4283 switch(m_spellInfo
->Effect
[j
])
4285 case SPELL_EFFECT_WEAPON_DAMAGE
:
4286 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4287 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4288 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4289 if (j
< i
) // we must calculate only at last weapon effect
4295 // some spell specific modifiers
4296 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4298 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4299 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4300 bool normalized
= false;
4302 int32 spell_bonus
= 0; // bonus specific for spell
4303 switch(m_spellInfo
->SpellFamilyName
)
4305 case SPELLFAMILY_WARRIOR
:
4307 // Whirlwind, single only spell with 2 weapon white damage apply if have
4308 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4310 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4311 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4313 // Devastate bonus and sunder armor refresh
4314 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4317 // Need refresh all Sunder Armor auras from this caster
4318 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4319 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4321 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4322 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4323 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4324 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4326 (*itr
).second
->RefreshAura();
4327 stack
= (*itr
).second
->GetStackAmount();
4331 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4335 case SPELLFAMILY_ROGUE
:
4337 // Mutilate (for each hand)
4338 if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4342 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4347 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4348 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4350 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4359 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4363 case SPELLFAMILY_PALADIN
:
4365 // Seal of Command - receive benefit from Spell Damage and Healing
4366 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4368 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4369 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4370 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4374 case SPELLFAMILY_SHAMAN
:
4376 // Skyshatter Harness item set bonus
4378 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4380 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4381 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4383 // Stormstrike AP Buff
4384 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4386 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4394 int32 fixed_bonus
= 0;
4395 for (int j
= 0; j
< 3; j
++)
4397 switch(m_spellInfo
->Effect
[j
])
4399 case SPELL_EFFECT_WEAPON_DAMAGE
:
4400 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4401 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4403 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4404 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4407 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4408 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4410 // applied only to prev.effects fixed damage
4411 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4414 break; // not weapon damage effect, just skip
4418 // apply weaponDamagePercentMod to spell bonus also
4419 if(spellBonusNeedWeaponDamagePercentMod
)
4420 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4422 // non-weapon damage
4423 int32 bonus
= spell_bonus
+ fixed_bonus
;
4425 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4429 switch(m_attackType
)
4432 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4433 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4434 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4437 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4438 bonus
= int32(bonus
*weapon_total_pct
);
4441 // + weapon damage with applied weapon% dmg to base weapon damage in call
4442 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4445 bonus
= int32(bonus
*totalDamagePercentMod
);
4447 // prevent negative damage
4448 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4450 // Add melee damage bonuses (also check for negative)
4451 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4452 m_damage
+= eff_damage
;
4455 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4457 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4458 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4462 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4464 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4465 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4469 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4471 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4473 // wands don't have ammo
4474 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4477 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4479 if(pItem
->GetMaxStackCount()==1)
4481 // decrease durability for non-stackable throw weapon
4482 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4486 // decrease items amount for stackable throw weapon
4488 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4491 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4492 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4496 void Spell::EffectThreat(uint32
/*i*/)
4498 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4501 if(!unitTarget
->CanHaveThreatList())
4504 unitTarget
->AddThreat(m_caster
, float(damage
));
4507 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4511 if(!unitTarget
->isAlive())
4514 uint32 heal
= m_caster
->GetMaxHealth();
4519 void Spell::EffectInterruptCast(uint32
/*i*/)
4523 if(!unitTarget
->isAlive())
4526 // TODO: not all spells that used this effect apply cooldown at school spells
4527 // also exist case: apply cooldown to interrupted cast only and to all spells
4528 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4530 if (unitTarget
->m_currentSpells
[i
])
4532 // check if we can interrupt spell
4533 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4535 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4536 unitTarget
->InterruptSpell(i
,false);
4542 void Spell::EffectSummonObjectWild(uint32 i
)
4544 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4546 GameObject
* pGameObj
= new GameObject
;
4548 WorldObject
* target
= focusObject
;
4553 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4555 x
= m_targets
.m_destX
;
4556 y
= m_targets
.m_destY
;
4557 z
= m_targets
.m_destZ
;
4560 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4562 Map
*map
= target
->GetMap();
4564 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4565 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4571 int32 duration
= GetSpellDuration(m_spellInfo
);
4572 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4573 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4575 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4576 m_caster
->AddGameObject(pGameObj
);
4579 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4581 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4583 Player
*pl
= (Player
*)m_caster
;
4584 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4585 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4587 uint32 team
= ALLIANCE
;
4589 if(pl
->GetTeam() == team
)
4592 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4597 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4599 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4601 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4602 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4604 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4609 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4611 GameObject
* linkedGO
= new GameObject
;
4612 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4613 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
4615 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4616 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4618 m_caster
->AddGameObject(linkedGO
);
4630 void Spell::EffectScriptEffect(uint32 effIndex
)
4632 // TODO: we must implement hunter pet summon at login there (spell 6962)
4634 switch(m_spellInfo
->SpellFamilyName
)
4636 case SPELLFAMILY_GENERIC
:
4638 switch(m_spellInfo
->Id
)
4640 // PX-238 Winter Wondervolt TRAP
4643 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4646 for(int j
= 0; j
< 4; ++j
)
4647 if(unitTarget
->HasAura(spells
[j
],0))
4651 uint32 iTmpSpellId
= spells
[urand(0,3)];
4654 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4660 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4663 uint32 spell_id
= 0;
4666 case 1: spell_id
= 8854; break;
4667 default: spell_id
= 8855; break;
4670 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4673 // Brittle Armor - need remove one 24575 Brittle Armor aura
4675 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4677 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4679 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4681 // Orb teleport spells
4695 switch(m_spellInfo
->Id
)
4697 case 25140: spellid
= 32571; break;
4698 case 25143: spellid
= 32572; break;
4699 case 25650: spellid
= 30140; break;
4700 case 25652: spellid
= 30141; break;
4701 case 29128: spellid
= 32568; break;
4702 case 29129: spellid
= 32569; break;
4703 case 35376: spellid
= 25649; break;
4704 case 35727: spellid
= 35730; break;
4709 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4712 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4727 if(!unitTarget
|| !unitTarget
->isAlive())
4730 // Onyxia Scale Cloak
4731 if(unitTarget
->GetDummyAura(22683))
4735 m_caster
->CastSpell(unitTarget
, 22682, true);
4738 // Summon Black Qiraji Battle Tank
4744 // Prevent stacking of mounts
4745 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4747 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4748 if (unitTarget
->GetAreaId() == 3428)
4749 unitTarget
->CastSpell(unitTarget
, 25863, false);
4751 unitTarget
->CastSpell(unitTarget
, 26655, false);
4754 // Piccolo of the Flaming Fire
4757 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4759 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4765 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4766 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
4769 // Mirren's Drinking Hat
4773 switch ( urand(1,6) )
4775 case 1:case 2:case 3:
4776 item
= 23584;break; // Loch Modan Lager
4778 item
= 23585;break; // Stouthammer Lite
4780 item
= 23586;break; // Aerie Peak Pale Ale
4783 DoCreateItem(effIndex
,item
);
4789 // Removes snares and roots.
4790 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4791 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4792 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4796 Aura
*aur
= iter
->second
;
4797 if (!aur
->IsPositive()) //only remove negative spells
4799 // check for mechanic mask
4800 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4802 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4806 next
= Auras
.begin();
4818 unitTarget
->CastSpell(unitTarget
, 41131, true);
4821 // Force Cast - Portal Effect: Sunwell Isle
4827 unitTarget
->CastSpell(unitTarget
, 44870, true);
4830 // Goblin Weather Machine
4839 case 0: spellId
= 46740; break;
4840 case 1: spellId
= 46739; break;
4841 case 2: spellId
= 46738; break;
4842 case 3: spellId
= 46736; break;
4844 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4850 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4853 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4857 // Emblazon Runeblade
4863 unitTarget
->CastSpell(unitTarget
,51771,false);
4869 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4871 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4872 unitTarget
->CastSpell(unitTarget
, damage
, false);
4875 case 58418: // Portal to Orgrimmar
4876 case 58420: // Portal to Stormwind
4878 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
4881 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
4882 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
4884 if( ((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
) )
4885 unitTarget
->CastSpell(unitTarget
, spellID
, true);
4889 // random spell learn instead placeholder
4890 case 60893: // Northrend Alchemy Research
4891 case 61177: // Northrend Inscription Research
4892 case 61288: // Minor Inscription Research
4893 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4895 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4897 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4901 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4903 Player
* player
= (Player
*)m_caster
;
4905 // need replace effect 0 item by loot
4906 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4908 if(!player
->HasItemCount(reagent_id
,1))
4913 player
->DestroyItemCount (reagent_id
,count
,true);
4915 // create some random items
4916 player
->AutoStoreLoot(m_spellInfo
->Id
,LootTemplates_Spell
);
4918 // learn random explicit discovery recipe (if any)
4919 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4920 player
->learnSpell(discoveredSpell
,false);
4926 case SPELLFAMILY_WARLOCK
:
4928 switch(m_spellInfo
->Id
)
4930 // Healthstone creating spells
4942 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4943 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4945 if((*i
)->GetId() == 18692)
4950 else if((*i
)->GetId() == 18693)
4957 static uint32
const itypes
[8][3] = {
4958 { 5512,19004,19005}, // Minor Healthstone
4959 { 5511,19006,19007}, // Lesser Healthstone
4960 { 5509,19008,19009}, // Healthstone
4961 { 5510,19010,19011}, // Greater Healthstone
4962 { 9421,19012,19013}, // Major Healthstone
4963 {22103,22104,22105}, // Master Healthstone
4964 {36889,36890,36891}, // Demonic Healthstone
4965 {36892,36893,36894} // Fel Healthstone
4968 switch(m_spellInfo
->Id
)
4971 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4973 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4975 itemtype
=itypes
[2][rank
];break; // Healthstone
4977 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4979 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4981 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4983 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4985 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4989 DoCreateItem( effIndex
, itemtype
);
4992 // Everlasting Affliction
4995 // Need refresh caster corruption auras on target
4996 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4997 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4999 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5000 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
5001 spellInfo
->SpellFamilyFlags
& 0x0000000000000002LL
&&
5002 (*itr
).second
->GetCasterGUID()==m_caster
->GetGUID())
5003 (*itr
).second
->RefreshAura();
5010 case SPELLFAMILY_PRIEST
:
5012 switch(m_spellInfo
->Id
)
5014 // Pain and Suffering
5019 // Refresh Shadow Word: Pain on target
5020 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5021 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5023 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5024 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5025 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
5026 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5028 (*itr
).second
->RefreshAura();
5039 case SPELLFAMILY_HUNTER
:
5041 switch(m_spellInfo
->Id
)
5047 int32 basePoint
= 0;
5048 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5049 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5051 Aura
*aura
= (*i
).second
;
5052 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5054 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5055 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5056 if (!(familyFlag
& 0x000000800000C000LL
))
5058 // Refresh aura duration
5059 aura
->RefreshAura();
5061 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5062 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5064 spellId
= 53353; // 53353 Chimera Shot - Serpent
5065 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5067 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5068 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5070 spellId
= 53358; // 53358 Chimera Shot - Viper
5071 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5073 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5074 if (familyFlag
& 0x0000000000008000LL
)
5075 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5076 // ?? nothing say in spell desc (possibly need addition check)
5077 //if (familyFlag & 0x0000010000000000LL || // dot
5078 // familyFlag & 0x0000100000000000LL) // stun
5080 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5084 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5092 case SPELLFAMILY_PALADIN
:
5095 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5097 if(!unitTarget
|| !unitTarget
->isAlive())
5099 uint32 spellId1
= 0;
5100 uint32 spellId2
= 0;
5102 // Judgement self add switch
5103 switch (m_spellInfo
->Id
)
5105 case 41467: break; // Judgement
5106 case 53407: spellId1
= 20184; break; // Judgement of Justice
5107 case 20271: // Judgement of Light
5108 case 57774: spellId1
= 20185; break; // Judgement of Light
5109 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5113 // all seals have aura dummy in 2 effect
5114 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5115 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5117 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5118 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5119 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5121 spellId2
= (*itr
)->GetModifier()->m_amount
;
5122 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5128 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5130 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5134 case SPELLFAMILY_POTION
:
5136 switch(m_spellInfo
->Id
)
5143 unitTarget
->CastSpell(unitTarget
, 28694, true);
5151 // 25% chance of casting a random buff
5152 if(roll_chance_i(75))
5155 // triggered spells are 28703 to 28707
5156 // Note: some sources say, that there was the possibility of
5157 // receiving a debuff. However, this seems to be removed by a patch.
5158 const uint32 spellid
= 28703;
5160 // don't overwrite an existing aura
5161 for(uint8 i
=0; i
<5; i
++)
5162 if(unitTarget
->HasAura(spellid
+i
, 0))
5164 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5173 // 25% chance of casting Nightmare Pollen
5174 if(roll_chance_i(75))
5176 unitTarget
->CastSpell(unitTarget
, 28721, true);
5184 // normal DB scripted effect
5188 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5189 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5192 void Spell::EffectSanctuary(uint32
/*i*/)
5196 //unitTarget->CombatStop();
5198 unitTarget
->CombatStop();
5199 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5200 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5201 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5203 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5207 void Spell::EffectAddComboPoints(uint32
/*i*/)
5212 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5218 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5221 void Spell::EffectDuel(uint32 i
)
5223 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5226 Player
*caster
= (Player
*)m_caster
;
5227 Player
*target
= (Player
*)unitTarget
;
5229 // caster or target already have requested duel
5230 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5233 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5234 // Don't have to check the target's map since you cannot challenge someone across maps
5235 uint32 mapid
= caster
->GetMapId();
5236 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5238 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5242 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5243 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5245 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5249 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5250 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5252 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5256 //CREATE DUEL FLAG OBJECT
5257 GameObject
* pGameObj
= new GameObject
;
5259 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5261 Map
*map
= m_caster
->GetMap();
5262 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5263 map
, m_caster
->GetPhaseMask(),
5264 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5265 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5266 m_caster
->GetPositionZ(),
5267 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5273 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5274 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5275 int32 duration
= GetSpellDuration(m_spellInfo
);
5276 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5277 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5279 m_caster
->AddGameObject(pGameObj
);
5284 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5285 data
<< pGameObj
->GetGUID();
5286 data
<< caster
->GetGUID();
5287 caster
->GetSession()->SendPacket(&data
);
5288 target
->GetSession()->SendPacket(&data
);
5291 DuelInfo
*duel
= new DuelInfo
;
5292 duel
->initiator
= caster
;
5293 duel
->opponent
= target
;
5294 duel
->startTime
= 0;
5295 duel
->startTimer
= 0;
5296 caster
->duel
= duel
;
5298 DuelInfo
*duel2
= new DuelInfo
;
5299 duel2
->initiator
= caster
;
5300 duel2
->opponent
= caster
;
5301 duel2
->startTime
= 0;
5302 duel2
->startTimer
= 0;
5303 target
->duel
= duel2
;
5305 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5306 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5309 void Spell::EffectStuck(uint32
/*i*/)
5311 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5314 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5317 Player
* pTarget
= (Player
*)unitTarget
;
5319 sLog
.outDebug("Spell Effect: Stuck");
5320 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());
5322 if(pTarget
->isInFlight())
5325 // homebind location is loaded always
5326 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5328 // Stuck spell trigger Hearthstone cooldown
5329 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5332 Spell
spell(pTarget
,spellInfo
,true,0);
5333 spell
.SendSpellCooldown();
5336 void Spell::EffectSummonPlayer(uint32
/*i*/)
5338 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5341 // Evil Twin (ignore player summon, but hide this for summoner)
5342 if(unitTarget
->GetDummyAura(23445))
5346 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5348 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5350 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5351 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5352 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5353 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5354 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5357 static ScriptInfo
generateActivateCommand()
5360 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5364 void Spell::EffectActivateObject(uint32 effect_idx
)
5369 static ScriptInfo activateCommand
= generateActivateCommand();
5371 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5373 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5376 void Spell::EffectApplyGlyph(uint32 i
)
5378 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5381 Player
*player
= (Player
*)m_caster
;
5384 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5386 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5388 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5390 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5392 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5393 return; // glyph slot mismatch
5398 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5400 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5402 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5403 player
->SetGlyph(m_glyphIndex
, 0);
5407 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5408 player
->SetGlyph(m_glyphIndex
, glyph
);
5413 void Spell::EffectSummonTotem(uint32 i
)
5416 switch(m_spellInfo
->EffectMiscValueB
[i
])
5418 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5419 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5420 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5421 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5422 // Battle standard case
5423 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5424 // jewelery statue case, like totem without slot
5425 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5429 if(slot
< MAX_TOTEM
)
5431 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5434 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5435 if(OldTotem
&& OldTotem
->isTotem())
5436 ((Totem
*)OldTotem
)->UnSummon();
5441 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5442 team
= ((Player
*)m_caster
)->GetTeam();
5444 Totem
* pTotem
= new Totem
;
5446 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5447 m_spellInfo
->EffectMiscValue
[i
], team
))
5453 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5456 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5458 // totem must be at same Z in case swimming caster and etc.
5459 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5460 z
= m_caster
->GetPositionZ();
5462 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5464 if(slot
< MAX_TOTEM
)
5465 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5467 pTotem
->SetOwner(m_caster
->GetGUID());
5468 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5470 int32 duration
=GetSpellDuration(m_spellInfo
);
5471 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5472 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5473 pTotem
->SetDuration(duration
);
5475 if (damage
) // if not spell info, DB values used
5477 pTotem
->SetMaxHealth(damage
);
5478 pTotem
->SetHealth(damage
);
5481 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5483 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5484 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5486 pTotem
->Summon(m_caster
);
5488 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5490 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5491 data
<< uint8(slot
);
5492 data
<< uint64(pTotem
->GetGUID());
5493 data
<< uint32(duration
);
5494 data
<< uint32(m_spellInfo
->Id
);
5495 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5499 void Spell::EffectEnchantHeldItem(uint32 i
)
5501 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5502 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5505 Player
* item_owner
= (Player
*)unitTarget
;
5506 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5512 if(!item
->IsEquipped())
5515 if (m_spellInfo
->EffectMiscValue
[i
])
5517 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5518 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5520 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5522 duration
= 10; //10 seconds for enchants which don't have listed duration
5524 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5528 // Always go to temp enchantment slot
5529 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5531 // Enchantment will not be applied if a different one already exists
5532 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5535 // Apply the temporary enchantment
5536 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
5537 item_owner
->ApplyEnchantment(item
,slot
,true);
5541 void Spell::EffectDisEnchant(uint32
/*i*/)
5543 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5546 Player
* p_caster
= (Player
*)m_caster
;
5547 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5550 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5552 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5554 // item will be removed at disenchanting end
5557 void Spell::EffectInebriate(uint32
/*i*/)
5559 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5562 Player
*player
= (Player
*)unitTarget
;
5563 uint16 currentDrunk
= player
->GetDrunkValue();
5564 uint16 drunkMod
= damage
* 256;
5565 if (currentDrunk
+ drunkMod
> 0xFFFF)
5566 currentDrunk
= 0xFFFF;
5568 currentDrunk
+= drunkMod
;
5569 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5572 void Spell::EffectFeedPet(uint32 i
)
5574 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5577 Player
*_player
= (Player
*)m_caster
;
5579 Item
* foodItem
= m_targets
.getItemTarget();
5583 Pet
*pet
= _player
->GetPet();
5590 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5595 _player
->DestroyItemCount(foodItem
,count
,true);
5596 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5598 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5601 void Spell::EffectDismissPet(uint32
/*i*/)
5603 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5606 Pet
* pet
= m_caster
->GetPet();
5608 // not let dismiss dead pet
5609 if(!pet
||!pet
->isAlive())
5612 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5615 void Spell::EffectSummonObject(uint32 i
)
5617 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5620 switch(m_spellInfo
->Effect
[i
])
5622 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5623 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5624 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5625 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5629 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5632 GameObject
* obj
= NULL
;
5634 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5636 if(obj
) obj
->Delete();
5637 m_caster
->m_ObjectSlot
[slot
] = 0;
5640 GameObject
* pGameObj
= new GameObject
;
5643 // If dest location if present
5644 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5646 x
= m_targets
.m_destX
;
5647 y
= m_targets
.m_destY
;
5648 z
= m_targets
.m_destZ
;
5650 // Summon in random point all other units if location present
5652 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5654 Map
*map
= m_caster
->GetMap();
5655 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5656 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, 1))
5662 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5663 int32 duration
= GetSpellDuration(m_spellInfo
);
5664 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5665 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5666 m_caster
->AddGameObject(pGameObj
);
5669 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5670 data
<< pGameObj
->GetGUID();
5671 m_caster
->SendMessageToSet(&data
,true);
5673 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5676 void Spell::EffectResurrect(uint32
/*effIndex*/)
5680 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5683 if(unitTarget
->isAlive())
5685 if(!unitTarget
->IsInWorld())
5688 switch (m_spellInfo
->Id
)
5690 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5692 if (roll_chance_i(67))
5694 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5698 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5700 if (roll_chance_i(50))
5702 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5710 Player
* pTarget
= ((Player
*)unitTarget
);
5712 if(pTarget
->isRessurectRequested()) // already have one active request
5715 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5716 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5718 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5719 SendResurrectRequest(pTarget
);
5722 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5724 if(!unitTarget
|| !unitTarget
->isAlive())
5727 if( unitTarget
->m_extraAttacks
)
5730 unitTarget
->m_extraAttacks
= damage
;
5733 void Spell::EffectParry(uint32
/*i*/)
5735 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5736 ((Player
*)unitTarget
)->SetCanParry(true);
5739 void Spell::EffectBlock(uint32
/*i*/)
5741 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5742 ((Player
*)unitTarget
)->SetCanBlock(true);
5745 void Spell::EffectMomentMove(uint32 i
)
5747 if(unitTarget
->isInFlight())
5750 if( m_spellInfo
->rangeIndex
== 1) //self range
5752 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5756 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5758 unitTarget
->GetPosition(ox
,oy
,oz
);
5760 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5761 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5766 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5769 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(),unitTarget
==m_caster
);
5773 void Spell::EffectReputation(uint32 i
)
5775 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5778 Player
*_player
= (Player
*)unitTarget
;
5780 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5782 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5784 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5789 _player
->GetReputationMgr().ModifyReputation(factionEntry
,rep_change
);
5792 void Spell::EffectQuestComplete(uint32 i
)
5794 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5797 Player
*_player
= (Player
*)m_caster
;
5799 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5800 _player
->AreaExploredOrEventHappens(quest_id
);
5803 void Spell::EffectSelfResurrect(uint32 i
)
5805 if(!unitTarget
|| unitTarget
->isAlive())
5807 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5809 if(!unitTarget
->IsInWorld())
5818 health
= uint32(-damage
);
5819 mana
= m_spellInfo
->EffectMiscValue
[i
];
5824 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5825 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5826 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5829 Player
*plr
= ((Player
*)unitTarget
);
5830 plr
->ResurrectPlayer(0.0f
);
5832 plr
->SetHealth( health
);
5833 plr
->SetPower(POWER_MANA
, mana
);
5834 plr
->SetPower(POWER_RAGE
, 0 );
5835 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5837 plr
->SpawnCorpseBones();
5842 void Spell::EffectSkinning(uint32
/*i*/)
5844 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5846 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5849 Creature
* creature
= (Creature
*) unitTarget
;
5850 int32 targetLevel
= creature
->getLevel();
5852 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5854 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5855 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5857 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5859 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5861 // Double chances for elites
5862 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5865 void Spell::EffectCharge(uint32
/*i*/)
5867 if(!unitTarget
|| !m_caster
)
5871 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5872 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5873 ((Creature
*)unitTarget
)->StopMoving();
5875 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5876 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5878 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5879 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5881 // not all charge effects used in negative spells
5882 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5883 m_caster
->Attack(unitTarget
,true);
5886 void Spell::EffectSummonCritter(uint32 i
)
5888 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5890 Player
* player
= (Player
*)m_caster
;
5892 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5896 Pet
* old_critter
= player
->GetMiniPet();
5898 // for same pet just despawn
5899 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5901 player
->RemoveMiniPet();
5905 // despawn old pet before summon new
5907 player
->RemoveMiniPet();
5910 Pet
* critter
= new Pet(MINI_PET
);
5912 Map
*map
= m_caster
->GetMap();
5913 uint32 pet_number
= objmgr
.GeneratePetNumber();
5914 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5915 pet_entry
, pet_number
))
5917 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5923 // If dest location if present
5924 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5926 x
= m_targets
.m_destX
;
5927 y
= m_targets
.m_destY
;
5928 z
= m_targets
.m_destZ
;
5930 // Summon if dest location not present near caster
5932 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5934 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5936 if(!critter
->IsPositionValid())
5938 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5939 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5944 critter
->SetOwnerGUID(m_caster
->GetGUID());
5945 critter
->SetCreatorGUID(m_caster
->GetGUID());
5946 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5947 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5949 critter
->AIM_Initialize();
5950 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5951 critter
->SetMaxHealth(1);
5952 critter
->SetHealth(1);
5953 critter
->SetLevel(1);
5955 // set timer for unsummon
5956 int32 duration
= GetSpellDuration(m_spellInfo
);
5958 critter
->SetDuration(duration
);
5960 std::string name
= player
->GetName();
5961 name
.append(petTypeSuffix
[critter
->getPetType()]);
5962 critter
->SetName( name
);
5963 player
->SetMiniPet(critter
);
5965 map
->Add((Creature
*)critter
);
5968 void Spell::EffectKnockBack(uint32 i
)
5970 if(!unitTarget
|| !m_caster
)
5973 // Effect only works on players
5974 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5977 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5978 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5980 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5981 data
.append(unitTarget
->GetPackGUID());
5982 data
<< uint32(0); // Sequence
5983 data
<< float(vcos
); // x direction
5984 data
<< float(vsin
); // y direction
5985 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5986 data
<< float(damage
/-10); // Z Movement speed (vertical)
5988 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5991 void Spell::EffectSendTaxi(uint32 i
)
5993 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5996 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
6000 std::vector
<uint32
> nodes
;
6003 nodes
[0] = entry
->from
;
6004 nodes
[1] = entry
->to
;
6007 switch(m_spellInfo
->Id
)
6009 case 31606: //Stormcrow Amulet
6012 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
6013 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
6014 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
6017 case 34905: //Stealth Flight
6020 case 45883: //Amber Ledge to Beryl Point
6023 case 46064: //Amber Ledge to Coldarra
6026 case 53335: //Stormwind Harbor Flight - Peaceful
6031 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
6035 void Spell::EffectPlayerPull(uint32 i
)
6037 if(!unitTarget
|| !m_caster
)
6040 // Effect only works on players
6041 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6044 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6045 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6047 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
6048 data
.append(unitTarget
->GetPackGUID());
6049 data
<< uint32(0); // Sequence
6050 data
<< float(vcos
); // x direction
6051 data
<< float(vsin
); // y direction
6053 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6054 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6056 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6059 void Spell::EffectDispelMechanic(uint32 i
)
6064 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6066 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6067 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6071 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6072 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6074 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6078 next
= Auras
.begin();
6084 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6086 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6088 Player
*_player
= (Player
*)m_caster
;
6089 Pet
*pet
= _player
->GetPet();
6096 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6097 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6098 pet
->setDeathState( ALIVE
);
6099 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6100 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6102 pet
->AIM_Initialize();
6104 _player
->PetSpellInitialize();
6105 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6108 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6111 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6113 if(!m_caster
->m_TotemSlot
[slot
])
6116 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6117 if(totem
&& totem
->isTotem())
6119 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6120 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6122 mana
+= spellInfo
->manaCost
* damage
/ 100;
6123 ((Totem
*)totem
)->UnSummon();
6127 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6128 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6131 void Spell::EffectDurabilityDamage(uint32 i
)
6133 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6136 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6138 // FIXME: some spells effects have value -1/-2
6139 // Possibly its mean -1 all player equipped items and -2 all items
6142 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6146 // invalid slot value
6147 if(slot
>= INVENTORY_SLOT_BAG_END
)
6150 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6151 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6154 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6156 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6159 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6161 // FIXME: some spells effects have value -1/-2
6162 // Possibly its mean -1 all player equipped items and -2 all items
6165 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6169 // invalid slot value
6170 if(slot
>= INVENTORY_SLOT_BAG_END
)
6176 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6177 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6180 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6185 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6188 void Spell::EffectTransmitted(uint32 effIndex
)
6190 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6192 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6196 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6202 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6204 fx
= m_targets
.m_destX
;
6205 fy
= m_targets
.m_destY
;
6206 fz
= m_targets
.m_destZ
;
6208 //FIXME: this can be better check for most objects but still hack
6209 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6211 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6212 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6216 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6217 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6218 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6220 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6223 Map
*cMap
= m_caster
->GetMap();
6225 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6227 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6228 { // but this is not proper, we really need to ignore not materialized objects
6229 SendCastResult(SPELL_FAILED_NOT_HERE
);
6230 SendChannelUpdate(0);
6234 // replace by water level in this case
6235 fz
= cMap
->GetWaterLevel(fx
,fy
);
6237 // if gameobject is summoning object, it should be spawned right on caster's position
6238 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6240 m_caster
->GetPosition(fx
,fy
,fz
);
6243 GameObject
* pGameObj
= new GameObject
;
6245 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6246 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6252 int32 duration
= GetSpellDuration(m_spellInfo
);
6254 switch(goinfo
->type
)
6256 case GAMEOBJECT_TYPE_FISHINGNODE
:
6258 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6259 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6261 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6262 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6266 case 0: lastSec
= 3; break;
6267 case 1: lastSec
= 7; break;
6268 case 2: lastSec
= 13; break;
6269 case 3: lastSec
= 17; break;
6272 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6275 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6277 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6279 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6280 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6284 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6285 case GAMEOBJECT_TYPE_CHEST
:
6292 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6294 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6296 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6297 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6299 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6300 //m_caster->AddGameObject(pGameObj);
6301 //m_ObjToDel.push_back(pGameObj);
6303 cMap
->Add(pGameObj
);
6305 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6306 data
<< uint64(pGameObj
->GetGUID());
6307 m_caster
->SendMessageToSet(&data
,true);
6309 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6311 GameObject
* linkedGO
= new GameObject
;
6312 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6313 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, 1))
6315 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6316 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6317 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6318 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6320 linkedGO
->GetMap()->Add(linkedGO
);
6331 void Spell::EffectProspecting(uint32
/*i*/)
6333 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6336 Player
* p_caster
= (Player
*)m_caster
;
6337 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6340 if(itemTarget
->GetCount() < 5)
6343 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6345 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6346 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6347 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6350 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6353 void Spell::EffectMilling(uint32
/*i*/)
6355 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6358 Player
* p_caster
= (Player
*)m_caster
;
6359 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6362 if(itemTarget
->GetCount() < 5)
6365 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6367 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6368 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6369 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6372 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6375 void Spell::EffectSkill(uint32
/*i*/)
6377 sLog
.outDebug("WORLD: SkillEFFECT");
6380 void Spell::EffectSummonDemon(uint32 i
)
6382 // select center of summon position
6383 float center_x
= m_targets
.m_destX
;
6384 float center_y
= m_targets
.m_destY
;
6385 float center_z
= m_targets
.m_destZ
;
6387 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6389 int32 amount
= damage
> 0 ? damage
: 1;
6391 for(int32 count
= 0; count
< amount
; ++count
)
6394 // If dest location if present
6395 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6397 // Summon 1 unit in dest location
6400 px
= m_targets
.m_destX
;
6401 py
= m_targets
.m_destY
;
6402 pz
= m_targets
.m_destZ
;
6404 // Summon in random point all other units if location present
6406 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
6408 // Summon if dest location not present near caster
6410 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
6412 int32 duration
= GetSpellDuration(m_spellInfo
);
6414 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,duration
);
6415 if (!Charmed
) // something fatal, not attempt more
6418 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6419 Charmed
->SetLevel(m_caster
->getLevel());
6421 // TODO: Add damage/mana/hp according to level
6423 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6425 // Enslave demon effect, without mana cost and cooldown
6426 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6429 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6434 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6435 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6436 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6437 This is why we use a half sec delay between the visual effect and the resurrection itself */
6438 void Spell::EffectSpiritHeal(uint32
/*i*/)
6441 if(!unitTarget || unitTarget->isAlive())
6443 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6445 if(!unitTarget->IsInWorld())
6448 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6449 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6450 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6451 ((Player*)unitTarget)->SpawnCorpseBones();
6455 // remove insignia spell effect
6456 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6458 sLog
.outDebug("Effect: SkinPlayerCorpse");
6459 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6462 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6465 void Spell::EffectStealBeneficialBuff(uint32 i
)
6467 sLog
.outDebug("Effect: StealBeneficialBuff");
6469 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6472 std::vector
<Aura
*> steal_list
;
6473 // Create dispel mask by dispel type
6474 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6475 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6476 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6478 Aura
*aur
= (*itr
).second
;
6479 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6481 // Need check for passive? this
6482 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6483 steal_list
.push_back(aur
);
6486 // Ok if exist some buffs for dispel try dispel it
6487 if (!steal_list
.empty())
6489 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6490 int32 list_size
= steal_list
.size();
6491 // Dispell N = damage buffs (or while exist buffs for dispel)
6492 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6494 // Random select buff for dispel
6495 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6496 // Not use chance for steal
6497 // TODO possible need do it
6498 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6500 // Remove buff from list for prevent doubles
6501 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6504 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6506 j
= steal_list
.erase(j
);
6513 // Really try steal and send log
6514 if (!success_list
.empty())
6516 int32 count
= success_list
.size();
6517 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6518 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6519 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6520 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6521 data
<< uint8(0); // not used
6522 data
<< uint32(count
); // count
6523 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6525 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6526 data
<< uint32(spellInfo
->Id
); // Spell Id
6527 data
<< uint8(0); // 0 - steals !=0 transfers
6528 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6530 m_caster
->SendMessageToSet(&data
, true);
6535 void Spell::EffectKillCredit(uint32 i
)
6537 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6540 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6543 void Spell::EffectQuestFail(uint32 i
)
6545 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6548 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6551 void Spell::EffectActivateRune(uint32 eff_idx
)
6553 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6556 Player
*plr
= (Player
*)m_caster
;
6558 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6561 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6563 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6565 plr
->SetRuneCooldown(j
, 0);
6570 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6572 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6573 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6576 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6578 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6579 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6582 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);